PInvokeStackImbalance C#调用非托pipeC ++函数
切换到VS2010后,托pipe的debugging助手显示一个关于从C#应用程序调用非托pipeC ++函数的不平衡堆栈的错误。
通常的嫌疑人似乎不会造成这个问题。 还有什么我应该检查? VS2008内置的C ++ DLL和C#应用程序从来没有问题,没有奇怪的或神秘的错误 – 是的,我知道这并不意味着太多。
这是检查的事情:
- 该dll名称是正确的。
- 入口点名称是正确的,并已通过depends.exe进行validation – 代码必须使用损坏的名称,它的确如此。
- 调用约定是正确的。
- 大小和types似乎都是正确的。
- 字符集是正确的。
- 在忽略错误之后似乎没有任何问题,并且在debugging器外部运行时没有问题。
C#:
[DllImport("Correct.dll", EntryPoint = "SuperSpecialOpenFileFunc", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true)] public static extern short SuperSpecialOpenFileFunc(ref SuperSpecialStruct stuff); [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] public struct SuperSpecialStruct { public int field1; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string field2; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string field3; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public string field4; public ushort field5; public ushort field6; public ushort field7; public short field8; public short field9; public uint field10; public short field11; };
C ++:
short SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff); struct SuperSpecialStruct { int field1; char field2[256]; char field3[20]; char field4[10]; unsigned short field5; unsigned short field6; unsigned short field7; short field8; short field9; unsigned int field10; short field11; };
这是错误:
托pipedebugging助手“PInvokeStackImbalance”在“托pipe应用程序path”中检测到问题。
附加信息:对PInvoke函数“SuperSpecialOpenFileFunc”的调用不平衡堆栈。 这很可能是因为托pipePInvoke签名与非托pipe目标签名不匹配。 检查PInvoke签名的调用约定和参数是否与目标非托pipe签名相匹配。
正如Dane Rose的评论所述 ,您可以在您的C ++函数上使用__stdcall
或在您的DllImport
上声明CallingConvention = CallingConvention.Cdecl
。
这是解决我的问题的答案。
你在C#中指定stdcall而不是在C ++中,这里的不匹配会导致函数和调用者从堆栈中popup参数。
另一方面有一个编译器开关将打开默认调用约定stdcall,(-GZ)你使用的是?
或者在你的C ++中试试这个
short __stdcall SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
在结构的C#声明中没有填充,但在C ++版本中没有填充。 由于您要混合的char数组不是所有的四倍数和奇数的两个字节的短数,所以编译器可能会在结构中插入填充并添加结尾。
尝试将结构包装在#pragma pack
以确保没有填充。
#pragma pack(push) #pragma pack(1) // The struct #pragma pack(pop)
有同样的问题所描述的 – 非托pipe的C ++应用程序已经完美工作多年。 当我们升级到VS2010时,我们开始得到PInvokeStackUnbalanced消息。
如上所述将“__stdcall”添加到C ++签名使问题消失。
这是很好的。我更新的function定义如下:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
它运作良好。