2009-09-24 2 views
5

У меня есть проект cll dll (my_cs_dll.dll), который определяет статический класс со статической функцией-членом.Как вы называете управляемую (C#) функцию из C++?

namespace Foo 
{ 
    public static class Bar 
    { 
     public static double GetNumber() { return 1.0; } 
    } 
} 

У меня также есть проект dll C++, который использует/clr.

#using <my_cs_dll.dll> 

double get_number_from_cs() { return Foo::Bar::GetNumber(); } 

Я добавил ссылку на 'my_cs_dll.dll' в C++ проект Общих свойств раздела ссылки (копировать локальный/зависимости от копирования являются True).

И еще я добавил путь к 'my_cs_dll.dll' в проект конфигурации C++. Свойства конфигурации C/C++ Общие разделы «Разрешить # с использованием ссылок».

Все строит без ошибок, однако во время выполнения я продолжаю получать исключение «System.IO.FileNotFound» из системы, заявляя, что не может найти сборку my_cs_dll.dll.

Оба Dll, безусловно, присутствуют в том же каталоге, с которого я работаю.

Я пробовал все виды вариаций настроек, указанных выше, и читать все, что смог найти на сведущих/неуправляемый Interop, но я не могу показаться, чтобы получить мой мозг вокруг, что это неправильно ...

I используя VS2008 & .NET 3.5

ответ

4

Похоже, что ваша сборка C# не разрешается во время выполнения. Является ли ваша C# dll в том же каталоге, что и (или подкаталог) вашего исполняемого файла? Это было давно, но я помню, что если ваша сборка не установлена ​​в GAC, она должна находиться в каталоге (или подкаталоге), где находится ваш исполняемый файл, в отличие от расположения используемой библиотеки dll Это. Это связано с функциями безопасности .NET.

Если у вас по-прежнему возникают проблемы, вы можете попробовать самостоятельно решить проблему сборки. В вашем проекте CLR с поддержкой C++, попробуйте добавить следующее:

using namespace System; 
using namespace System.Reflection; 
void Resolve() 
{ 
    AppDomain::CurrentDomain->AssemblyResolve += 
     gcnew ResolveEventHandler(OnAssemblyResolve); 
} 
Assembly ^OnAssemblyResolve(Object ^obj, ResolveEventArgs ^args) 
{ 
#ifdef _DEBUG 
    String ^path = gcnew String(_T("<path to your debug directory>")); 
#else 
    String ^path = gcnew String(_T("<path to your release directory>")); 
#endif 
    array<String^>^ assemblies = 
     System::IO::Directory::GetFiles(path, _T("*.dll")); 
    for (long ii = 0; ii < assemblies->Length; ii++) { 
     AssemblyName ^name = AssemblyName::GetAssemblyName(assemblies[ii]); 
     if (AssemblyName::ReferenceMatchesDefinition(gcnew AssemblyName(args->Name), name)) { 
      return Assembly::Load(name); 
     } 
    } 
    return nullptr; 
} 

Вы, возможно, придется настроить код немного, чтобы получить его для компиляции в вашем проекте. В моем случае я сделал две функции статических методов класса в моем проекте с поддержкой clr. Просто убедитесь, что вы вызываете функцию Resolve() на раннем этапе вашего кода, т. Е. Перед тем, как попытаться позвонить get_number_from_cs().

При использовании опции COM это необязательно. Вы находитесь на правильном пути с вашим текущим подходом. Если вы хотите получить немного рук, взгляните на это CodeProject example. Это я следую за тем, чтобы мое неуправляемое приложение использовало мои управляемые сборки.

+0

Привет Matt, «он должен находиться в каталоге (или подкаталог), где находится исполняемый, в отличие от расположения библиотеки DLL, которые используют его» В DLL файлов вложены несколько подкаталогов под ех , Перемещение управляемой DLL в ту же директорию, что и исполняемый, устраняет проблему. спасибо !! – mark

+0

Хорошо, отлично. У меня создалось впечатление, что до тех пор, пока dll находится в подкаталоге исполняемого файла, независимо от того, насколько глубока, сборка будет решена. Но, как я уже сказал, прошло некоторое время с тех пор, как я посмотрел на это. –

+0

Я использовал аналогичный код при загрузке DLL C# из встроенного ресурса. Трюк заключался в том, чтобы поместить этот код в файл, который не ссылался на C# DLL. Кажется, что задержка-загрузка.Чистые сборки возникают при вводе в блок компиляции (файл .cpp), который содержит ссылку на рассматриваемую сборку, а не когда вызов в ссылочной сборке фактически выполнен, если когда-либо. – mheyman

Смежные вопросы