2009-09-24 90 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

相关问题