![](/img/trans.png)
[英]Solution to PInvokeStackImbalance exception (Calling unmanaged C++ dll from C#) - VS2010
[英]PInvokeStackImbalance C# call to unmanaged C++ function
切换到 VS2010 后,托管调试助手显示有关从 C# 应用程序调用非托管 C++ 函数导致堆栈不平衡的错误。
通常的嫌疑人似乎并没有引起这个问题。 还有什么我应该检查的吗? VS2008 构建的 C++ dll 和 C# 应用程序从来没有出现过问题,没有奇怪或神秘的错误 - 是的,我知道这没有多大意义。
以下是检查的内容:
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;
};
这是错误:
托管调试助手“PInvokeStackImbalance”在“托管应用程序路径”中检测到问题。
附加信息:对 PInvoke 函数“SuperSpecialOpenFileFunc”的调用使堆栈不平衡。 这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。 检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。
正如Dane Rose 的评论中提到的,您可以在 C++ 函数上使用__stdcall
或在DllImport
上声明CallingConvention = CallingConvention.Cdecl
。
您在 C# 中指定 stdcall 而不是在 C++ 中,此处的不匹配将导致函数和调用者都从堆栈中弹出参数。
另一方面,有一个编译器开关将打开 stdcall 作为默认调用约定,(-Gz) 你在使用它吗?
或者在你的 C++ 中试试这个
short __stdcall SuperSpecialOpenFileFunc(SuperSpecialStruct * stuff);
您在结构的 C# 声明中没有指定填充,但在 C++ 版本中没有指定。 由于您混合的字符数组并非全部为 4 的倍数和奇数个 2 字节短整数,因此编译器可能会在结构中插入填充并添加结尾。
尝试将结构包装在#pragma pack
以确保没有填充。
#pragma pack(push)
#pragma pack(1)
// The struct
#pragma pack(pop)
遇到了与描述相同的问题 - 多年来一直完美运行的非托管 C++ 应用程序。 当我们升级到 VS2010 时,我们开始收到 PInvokeStackUnbalanced 消息。
如上所述将“__stdcall”添加到 C++ 签名使问题消失。
很好。我更新函数定义如下:
[DllImport("mydll.dll", CallingConvention = CallingConvention.Cdecl)]
它运作良好。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.