首页 > 后端开发 > C++ > 为什么__STDCALL C和CDECL C#调用P/Invoke中的冲突,如何解决?

为什么__STDCALL C和CDECL C#调用P/Invoke中的冲突,如何解决?

Barbara Streisand
发布: 2025-01-25 23:46:11
原创
227 人浏览过

Why Do __stdcall C   and Cdecl C# Calls Conflict in P/Invoke, and How Can This Be Resolved?

理解 P/Invoke 中的 Cdecl/__stdcall 冲突

P/Invoke 连接 C# 和 C,依赖匹配的调用约定来确保正确的参数传递和堆栈管理。 当使用默认(通常是 __stdcall)P/Invoke 约定从 C# 调用使用 cdecl 约定的 C 函数时,会出现一个常见问题。

问题的根源

不同的调用约定以不同的方式处理堆栈清理:

  • __stdcall:广泛用于 Windows API 和 COM,被调用者(C 函数)负责清理堆栈。
  • __cdecl:默认的 C 调用约定,调用者(C# 代码)处理堆栈清理。
  • __thiscall:用于C成员函数;由于其复杂性,P/Invoke 不直接支持它。

不匹配的后果

仅将 extern "C" 添加到 C 代码并在 C# CallingConvention.Cdecl 属性中指定 DllImport 并不能解决问题。 不同的清理职责会导致堆栈损坏,甚至可能导致崩溃或微妙的、难以调试的错误,即使没有立即发出调试器警告。 堆栈可能会被清理两次,从而导致不可预测的行为。

解决方案:一致的约定

关键是一致性。 修改 C 函数声明以显式使用 __cdecl:将 extern "C" int __stdcall InvokedFunction(int); 替换为 extern "C" int __cdecl InvokedFunction(int);。 然后,确保您的 C# DllImport 属性匹配:

<code class="language-csharp">[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]</code>
登录后复制

要点

仔细注意调用约定对于可靠的 P/Invoke 互操作性至关重要。 在 C 和 C# 之间使用一致的约定可以消除堆栈不平衡并提高代码的整体稳健性。

以上是为什么__STDCALL C和CDECL C#调用P/Invoke中的冲突,如何解决?的详细内容。更多信息请关注PHP中文网其他相关文章!

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