首页 > 后端开发 > C++ > 为什么CDECL和Stdcall在C#p/Invoke中调用惯例不匹配,该如何解决?

为什么CDECL和Stdcall在C#p/Invoke中调用惯例不匹配,该如何解决?

Linda Hamilton
发布: 2025-01-25 23:36:13
原创
190 人浏览过

Why Do Cdecl and Stdcall Calling Conventions Mismatch in C# P/Invoke, and How Can This Be Fixed?

了解 C# P/Invoke 调用约定冲突:Cdecl 与 Stdcall

平台调用 (P/Invoke) 桥接托管 (C#) 和非托管(例如 C)代码。 然而,调用约定的差异可能会导致互操作性问题。

问题的根源

冲突源于 C 和 C# 中默认 P/Invoke 设置之间不同的调用约定处理。

  • C : C 函数通常采用 __stdcall 约定。 被调用的函数(callee)负责堆栈清理。
  • C# P/Invoke 默认值: C# 的 P/Invoke 默认为 CallingConvention.Winapi,在 Windows 上相当于 __stdcall

主要调用约定差异:

核心区别在于:

  • 约定关键字:C 中的 __stdcall 与 C# 中的 CallingConvention.Winapi(或 CallingConvention.Stdcall)。
  • 堆栈管理: __cdecl(C 中常用)需要调用函数(caller)清理堆栈; __stdcall 将其分配给 callee
  • 参数顺序:虽然在此特定上下文中作为错误来源不太常见,但参数顺序可能因约定而异。

不正确的 P/Invoke 声明示例:

当 C 函数使用 CallingConvention.Cdecl 时,不正确的 C# 声明可能会使用 __stdcall。这会导致堆栈损坏和运行时错误。

正确的 C# 声明:

为了确保兼容性,C# DllImport 属性必须匹配 C 函数的约定:

<code class="language-csharp">[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Winapi)]
private static extern int InvokedFunction(IntPtr intArg);</code>
登录后复制

防止约定不匹配:

始终确认非托管函数的调用约定并将其精确反映在您的 C# DllImport 声明中。 有关支持的调用约定的详细信息,请参阅 Microsoft 文档。

以上是为什么CDECL和Stdcall在C#p/Invoke中调用惯例不匹配,该如何解决?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板