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)] 

它运作良好。