首页 > 后端开发 > C++ > 为什么我的 C# P/Invoke 使用 `CallingConvention.Cdecl` 调用 C `__stdcall` 函数时失败?

为什么我的 C# P/Invoke 使用 `CallingConvention.Cdecl` 调用 C `__stdcall` 函数时失败?

Patricia Arquette
发布: 2025-01-25 23:51:11
原创
410 人浏览过

Why Does My C# P/Invoke Call With `CallingConvention.Cdecl` Fail When Calling a C   `__stdcall` Function?

C# P/Invoke 调用约定不匹配问题排查

本文解释了使用 Platform Invoke (P/Invoke) 在 C# 和 C 代码之间交互时的常见问题。 我们将重点关注调用约定不匹配的问题:C# 中的 CallingConvention.Cdecl 与 C 中的 __stdcall

调用约定解释

在 32 位环境中,调用约定决定参数传递、堆栈存储和清理。主要约定包括:

  • __stdcall: 调用者推送参数;被调用者清理堆栈。由 Windows API 和 COM 使用。
  • __cdecl: 调用者压入参数并清理堆栈。 C.
  • 标准
  • __fastcall: 使用寄存器来存储某些参数,可能会提高速度,但会降低兼容​​性。
  • __thiscall:__cdecl 类似,但处理 C 成员函数中的“this”指针。
  • __clrcall: 托管调用约定平衡其他元素,防止堆栈问题。

代码示例分析

考虑一个 C 函数:

<code class="language-c++">extern "C" int __stdcall InvokedFunction(int);</code>
登录后复制

及其 C# P/Invoke 对应项:

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

大会冲突

问题源于 C# 中的 CallingConvention.Cdecl 与 C 中的 __stdcall 冲突。这会导致堆栈不平衡。虽然 __stdcall 通常是 P/Invoke 默认值(由于其 Windows API 流行),但与 __cdecl C 代码交互需要显式约定规范。

分辨率

解决方案很简单:将 C# 调用约定与 C 调用约定对齐:

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

要点

理解调用约定对于成功的跨语言互操作性至关重要。 匹配约定可防止堆栈错误并确保 C# 和 C 的顺利集成。

以上是为什么我的 C# P/Invoke 使用 `CallingConvention.Cdecl` 调用 C `__stdcall` 函数时失败?的详细内容。更多信息请关注PHP中文网其他相关文章!

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