【发布时间】:2011-06-28 18:07:57
【问题描述】:
我目前正在为 Windows 开发一个 C++ 库,它将作为 DLL 分发。我的目标是最大化二进制互操作性;更准确地说,我的 DLL 中的函数必须可以从使用多个版本的 MSVC++ 和 MinGW 编译的代码中使用,而无需重新编译 DLL。但是,我对哪种调用约定最好感到困惑,cdecl 或 stdcall。
有时我会听到诸如“C 调用约定是唯一保证跨编译器相同的”之类的声明,这与“There are some variations in the interpretation of cdecl, particularly in how to return values”之类的声明形成鲜明对比。这似乎并没有阻止某些库开发人员(例如 libsndfile)在他们分发的 DLL 中使用 C 调用约定,而没有任何明显的问题。
另一方面,stdcall 调用约定似乎定义明确。据我所知,基本上所有 Windows 编译器都必须遵循它,因为它是用于 Win32 和 COM 的约定。这是基于这样的假设,即不支持 Win32/COM 的 Windows 编译器不会很有用。论坛上发布的许多代码 sn-ps 将函数声明为 stdcall,但我似乎无法找到一篇清楚地解释为什么的帖子。
那里有太多相互矛盾的信息,我运行的每次搜索都会给我不同的答案,这并不能真正帮助我在两者之间做出决定。我正在寻找一个清晰、详细、有争议的解释,说明为什么我应该选择一个而不是另一个(或者为什么两者是等价的)。
请注意,这个问题不仅适用于“经典”函数,还适用于虚拟成员函数调用,因为大多数客户端代码将通过“接口”与我的 DLL 交互,纯虚拟类(遵循描述的模式,例如 here 和there)。
【问题讨论】:
-
“cdecl 的解释有一些变化,特别是在如何返回值方面” - 这大致意味着在 x86 上使用 cdecl 的不同操作系统可能使用不同的 cdecl 变体,即它们使用不同的 ABI两者都称为“cdecl”。 Windows 确定了变化,任何在 Windows 上运行并且不尊重 Windows 选择的实现都将无法调用 Windows cdecl 函数,所以正如你所说的 stdcall,它对 Windows 编程没用,并且有一些标准 C很难实现的功能。
-
__stdcall 调用约定用于调用 Win32 API 函数。 docs.microsoft.com/en-us/cpp/cpp/stdcall?view=vs-2017
标签: c++ windows dll calling-convention binary-compatibility