我在一段时间内一直在使用的东西上遇到了这个奇怪的错误。它可能是Visual Studio 2010中的新功能,但我不确定
我试图用C#调用用C ++编写的无人函数。
从我在互联网上阅读的内容和错误信息本身来看,这与我的C#文件中的签名与C ++中的签名不同,但我真的看不到它。
首先,这是我在下面的无人函数:
TEngine GCreateEngine(int width,int height,int depth,int deviceType);
这是我在C#中的功能:
[DllImport("Engine.dll", EntryPoint = "GCreateEngine", CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr CreateEngine(int width,int height,int depth,int device);
当我调试到C ++时,我看到所有参数都很好,因此我只能认为它与从TEngine(一个名为CEngine的类的指针)转换为IntPtr有关。我之前在VS2008中使用过这个问题没有问题。
答案 0 :(得分:85)
我有一个_cdecl c ++ dll,我在Visual Studio 2008中没有遇到任何麻烦,然后Visual Studio 2010中的相同代码无效。我得到了相同的PInvoke ...也没有平衡堆栈错误。
我的解决方案是在DllImport(...)属性中指定调用约定: 从:
[DllImport(CudaLibDir)]
要:
[DllImport(CudaLibDir, CallingConvention = CallingConvention.Cdecl)]
我猜他们在.NET 3.5和.NET 4.0之间更改了DLLImport的默认调用约定?
答案 1 :(得分:48)
也可能是在.NET Framework 3.5版中,默认情况下禁用pInvokeStackImbalance MDA。在4.0(或者VS2010)下,它是enabled by default。
是。从技术上讲,代码总是错误的,以前的版本 框架默默地纠正了它。
引用.NET Framework 4 Migration Issues document:"改进 与非托管代码的互操作性能,不正确的调用 平台调用中的约定现在导致应用程序失败。在 以前的版本,编组层解决了这些错误 堆栈...如果您有无法更新的二进制文件,则可以包括 < NetFx40_PInvokeStackResilience>应用程序的配置文件中的元素以启用调用 像早期版本一样,要在堆栈中解决错误。然而, 这可能会影响您的应用程序的性能。"
解决此问题的一种简单方法是指定调用约定并确保它与DLL中的相同。 __declspec(dllexport)
应该产生 cdecl 格式。
[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]
答案 2 :(得分:21)
问题可能在于调用约定。你确定非托管函数被编译为stdcall而不是其他东西(我猜想快速调用)?
答案 3 :(得分:5)
使用以下代码,如果您的DLL名称为 MyDLL.dll ,并且您想在Dll中使用 MyFunction 功能
[DllImport("MyDLL.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern void MyFunction();
这对我有用。
答案 4 :(得分:2)
在我的情况下(VB 2010和使用英特尔Fortran 2011 XE编译的DLL),当我的应用程序面向.NET Framework 4时,问题就出现了。如果我将目标框架更改为版本3.5,那么一切都正常工作。 所以,我猜这个原因是.Net Framework 4中引入的内容,但我现在还不知道哪一个
更新:通过重新编译Fortran DLL并显式指定STDCALL作为DLL中导出名称的调用约定来解决问题。