繁体   English   中英

PInvokeStackImbalance C# 调用非托管 C++ 函数

[英]PInvokeStackImbalance C# call to unmanaged C++ function

切换到 VS2010 后,托管调试助手显示有关从 C# 应用程序调用非托管 C++ 函数导致堆栈不平衡的错误。

通常的嫌疑人似乎并没有引起这个问题。 还有什么我应该检查的吗? VS2008 构建的 C++ dll 和 C# 应用程序从来没有出现过问题,没有奇怪或神秘的错误 - 是的,我知道这没有多大意义。

以下是检查的内容:

  • dll名称正确。
  • 入口点名称是正确的,并且已经用depends.exe 进行了验证——代码必须使用损坏的名称,而且确实如此。
  • 调用约定是正确的。
  • 大小和类型似乎都是正确的。
  • 字符集是正确的。
  • 忽略错误后似乎没有任何问题,并且在调试器之外运行时也没有问题。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM