2009-09-24 22 views
5

我有一個c#dll項目(my_cs_dll.dll),它定義了靜態成員函數的靜態類。如何從C++調用託管(c#)函數?

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

我也有一個使用/ clr的C++ dll項目。

#using <my_cs_dll.dll> 

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

我已經添加在C到'my_cs_dll.dll'參考++項目通用屬性引用部分(複製本地/複製的依賴都是如此)。

而且我還在C++項目Configuration Properties C/C++ General'Resolve#using References'部分中添加了'my_cs_dll.dll'的路徑。

所有內容都沒有錯誤,但是在運行時,我一直從系統中得到一個'System.IO.FileNotFound'異常,聲稱它找不到my_cs_dll.dll程序集。

這兩個DLL都肯定存在於我運行的同一個目錄中。

我已經試過各種上文提到的設置變化和閱讀了所有我能找到manged /非託管互操作,但我似乎無法得到解決什麼是錯的我的大腦......

我使用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

馬特嗨, 「它必須在目錄(或子目錄)在您的可執行文件的位置,而不是DLL的位置,目前正使用它」 DLL的嵌套的exe下面幾個子目錄。將託管的dll移動到與可執行文件相同的目錄中,清除了問題。 謝謝! – mark 2009-09-24 07:02:22

+0

好,太好了。我的印象是,只要dll位於可執行文件的子目錄中,無論深度多大,程序集都將被解析。但正如我所說,從我看過這一段時間以來已經有一段時間了。 – 2009-09-24 07:04:55

+0

從嵌入式資源加載C#DLL時,我使用了類似的代碼。這裏的技巧是將這些代碼放在一個沒有引用C#DLL的文件中。看來,延遲加載的。網絡程序集在進入一個編譯單元(一個.cpp文件)時發生,該編譯單元包含對所討論的程序集的引用,而不是實際進行引用程序集的調用時(如果有的話)。 – mheyman 2013-02-07 15:44:41