对PInvoke函数'[...]'的调用使堆栈失衡

San*_*099 45 c# c++ pinvoke unmanaged managed

对于我已经使用了很长一段时间的一些东西,我得到了这个奇怪的错误.它可能是Visual Studio 2010中的新东西,但我不确定.
我试图用C#调用用C++编写的无人函数.
从我在互联网上阅读的内容和错误信息本身来看,这与我的C#文件中的签名与C++中的签名不同但我真的看不到它这一事实有关.
首先,这是我在下面的无人函数:

TEngine GCreateEngine(int width,int height,int depth,int deviceType);
Run Code Online (Sandbox Code Playgroud)

这是我在C#中的功能:

[DllImport("Engine.dll", EntryPoint = "GCreateEngine", CallingConvention = CallingConvention.StdCall)]  
        public static extern IntPtr CreateEngine(int width,int height,int depth,int device);
Run Code Online (Sandbox Code Playgroud)

当我调试到C++时,我看到所有的参数都很好,因此我只能认为它与从TEngine(这是一个名为CEngine的类的指针)转换为IntPtr有关.我之前在VS2008中使用过这个没问题.

Sco*_*ken 86

我有一个_cdecl c ++ dll,我在Visual Studio 2008中没有遇到任何麻烦,然后Visual Studio 2010中的相同代码无效.我得到了相同的PInvoke ...也没有平衡堆栈错误.

我的解决方案是在DllImport(...)属性中指定调用约定:From:

[DllImport(CudaLibDir)] 
Run Code Online (Sandbox Code Playgroud)

至:

[DllImport(CudaLibDir, CallingConvention = CallingConvention.Cdecl)]
Run Code Online (Sandbox Code Playgroud)

我猜他们改变了.NET 3.5和.NET 4.0之间DLLImport的默认调用约定?


Kei*_*son 49

也可能是在.NET Framework 3.5版中,默认情况下禁用pInvokeStackImbalance MDA.在4.0(或可能是VS2010)下,它默认启用.

是.从技术上讲,代码总是错误的,并且框架的先前版本默默地纠正了它.

引用.NET Framework 4迁移问题文档:"为了提高与非托管代码的互操作性能,平台调用中的错误调用约定现在导致应用程序失败.在以前的版本中,编组层将这些错误解决了堆栈.如果您有无法更新的二进制文件,可以在应用程序的配置文件中包含< NetFx40_PInvokeStackResilience >元素,以便在早期版本中将调用错误解析到堆栈中.但是,这可能会影响应用程序的性能.

解决此问题的一种简单方法是指定调用约定并确保它与DLL中的相同.A __declspec(dllexport)应该产生一个cdecl格式.

[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl)]
Run Code Online (Sandbox Code Playgroud)


Pet*_*erK 22

也许问题在于调用约定.你确定非托管函数被编译为stdcall而不是其他东西(我猜想快速调用)?


小智 5

使用以下代码,如果您的DLL名称为MyDLL.dll并且您想在Dll中使用函数MyFunction

[DllImport("MyDLL.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
public static extern void MyFunction();
Run Code Online (Sandbox Code Playgroud)

这对我有用.

  • 你在这做了什么不同的事情?为什么它解决了这个问题? (2认同)