C# cdecl
与 C __stdcall
在 P/Invoke 中共存的原因
在 C# 和 C 之间的 P/Invoke 互操作中,经常会出现 C# 函数使用 cdecl
调用约定,而其 C 对应函数使用 __stdcall
签名的情况。这种不匹配源于历史上延续至今的调用约定选择。
__stdcall
:Windows 函数的调用者清理
__stdcall
继承自 16 位 Pascal 调用约定,是 Windows API 函数和 COM 的默认调用约定。它规定被调用者 (正在调用的函数) 在执行后清理堆栈,使其在资源受限的环境中更紧凑。然而,如果调用者和被调用者期望的参数数量不匹配,这种优势就会带来堆栈不平衡的风险。
__cdecl
:可变参数函数的调用者清理
__cdecl
是 C 中的标准调用约定,用于具有可变数量参数的函数,例如 printf()
和 scanf()
。此约定将堆栈清理的责任放在调用者身上,因为调用者知道传递的参数数量。在 C# 的 [DllImport]
声明中忘记指定 CallingConvention.Cdecl
是一个常见的陷阱。
__thiscall
:C 方法的隐藏 this 指针
__thiscall
特指 C ,用于处理在类的实例方法中传递隐藏的 this
指针。它类似于 __cdecl
,但 .NET P/Invoke 封送处理程序不支持它,因此不适合用于 pinvoke C 代码。
总结
C# 中的 cdecl
调用和 C 中的 __stdcall
签名共存是这些历史调用约定以及每种语言特定要求的结果。正确理解这些约定,以及 [DllImport]
的 EntryPoint
和 ExactSpelling
属性,对于确保正确的 P/Invoke 功能并避免潜在问题(例如堆栈不平衡)至关重要。
以上是为什么c#`cdecl`呼叫和c` __ stdcall`签名在p/invoke中共存?的详细内容。更多信息请关注PHP中文网其他相关文章!