【发布时间】:2012-11-16 15:06:26
【问题描述】:
我有一个非托管 c++ DLL,它通过托管 c++ 包装器调用 c# 代码。非托管 c++ DLL 是某些应用程序的插件(不在我的控制范围内)。当此应用程序调用非托管 c++ DLL 时,一切正常,直到托管 c++ 代码尝试使用 c# 代码。然后它崩溃了。
我编写了一个测试应用程序,它与应用程序执行相同的操作,即调用非托管 c++ DLL。 这很好用。
代码尽可能简单:
非托管 c++:
extern "C" __declspec(dllexport) void UnmanagedMethodCalledUponByApplication()
{
new Bridge();
}
托管 c++:
Bridge::Brigde()
{
gcnew Managed(); // This line crashes
}
c#:
public class Managed
{
}
我尝试在有问题的行周围添加一个 try-catch (...) 块,但它没有捕捉到错误。
如果我用MessageBox::Show("Alive!"); 替换gcnew Managed(); 行,它可以正常工作。所以我的猜测是我的 c# 项目设置有问题。
我尝试用不同的平台(任何 CPU 和 x86)编译它。我试图改变目标框架。我试图在Managed 中调用静态方法,而不是使用gcnew。仍然崩溃。
任何想法可能是什么问题?
更新:
在 cmets 提出建议并回答后,我附加了调试器。现在我看到我收到了一个System.IO.FileNotFoundException,说找不到托管 DLL(或其依赖项之一)。
这里有一个猜测:这些 DLL 放在一起,但它们不在当前目录中。非托管 c++ DLL 正确加载,因为主应用程序指定了它的路径。托管 c++ 实际上是一个库,因此代码也可以正常工作。但是当托管 c++ 尝试加载 c# DLL 时,它会在错误的目录中查找它。
更新:
解决此问题的方法是使用反射动态加载 c# DLL。
【问题讨论】:
-
@pivotnig 是的,Bridge 不受管理。
-
可能宿主应用程序之前加载了不同版本的 .NET 运行时 (CLR),从而阻止您的代码加载它需要的代码。出于这个原因,不鼓励在插件中使用托管代码,尽管 .NET 4 在同一进程中并行加载多个版本方面取得了一些进展。
-
另外,在调试器中捕获异常。
-
当你调试应用程序并打开异常时——你得到的异常是什么。
标签: dll c++-cli managed managed-c++