C#调用C/C++动态库dll异常:对 PInvoke 函数调用导致堆栈不对称问题

发布时间 2023-07-28 17:43:12作者: wu.g.q

C#调用C/C++动态库dll异常:对 PInvoke 函数调用导致堆栈不对称问题

雨渡石桥

已于 2023-02-21 12:04:29 修改

973
收藏 1
文章标签: windows c++ c#
版权
结论:如果你是用C#调用C的动态库,如果出现“对 PInvoke 函数调用导致堆栈不对称问题”,建议优先调整CallingConvention的值,建议改为CallingConvention = CallingConvention.Winapi。此时C#会根据代码运行平台,自动选择正确的值。

环境:C#调用C生成的dll

代码:

 

 

问题描述:托管调试助手 "PInvokeStackImbalance":“对 PInvoke 函数“SuprDog!SuprDog.sntllicgen::Initialize”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。”

网上相关方法:

托管调试助手 "PInvokeStackImbalance":的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管 - wjw1990 - 博客园 (cnblogs.com)

但是以上方法并不能解决我的问题,遂尝试更改CallingConvention的值,改为CallingConvention = CallingConvention.Winapi后成功运行。以下是官方对CallingConvention的解释:

 

以下是通俗的理解(摘自CallingConvention理解 - 晨~光 - 博客园 (cnblogs.com)):

Cdecl:由调用者清理栈资源。非常适合用在可变参数的函数调用上,例如printf.

FastCall: Calling convention不支持。

StdCall:由被调用者清理栈资源。这是调用native函数时默认的方式。

ThisCall:第一个参数是this指针,会被存储在ECX寄存器里,而其它的参数会被压栈。这种方式通常用在调用未托管的DLL的方法或类。

Winapi:实际上并不是一个calling convention,实际上会被默认的平台的calling convention替代。例如window上调用,会替换成StdCall,Windows CE.NET上则被替换成Cdecl.

原文链接:https://blog.csdn.net/u010019329/article/details/129139627