[英]What is the standard way to manage calling-convention compatibility between a program and its DLL plugins?
我正在构建一个 C 程序,它显式地动态加载 DLL 作为插件系统的一部分。 我在 Windows 7 上使用 GCC 和 MinGW。
DLL 中导出的函数应该使用什么调用约定,以便尽可能健壮:在不同的 Windows 机器上成功运行,在不同的编译器版本中存活,等等。
我知道主可执行文件和 DLL 只需要使用相同的调用约定。 这通常是如何管理的?
目前,我的目标只是支持 Windows(尽管也欢迎在 Linux 上也提及同一主题的答案)。
编辑:
请让我澄清这个问题,正如在@SS Anne 的评论部分中所讨论的那样。
我不太关心特定的调用约定。 我更关心确保机器 X 上构建的二进制文件与机器 Y 上其他人构建的 DLL(插件)之间兼容性的标准方法是什么,这可能具有不同的操作系统等。
我能想到的一种方法是,在分发给插件开发人员的头文件中,我们定义了一个宏,用于指定插件向主程序公开的函数的预期调用约定。 这些函数将由插件开发人员使用此宏定义。
例如,提供给插件开发人员的api.h
头文件定义了#define CALL __cdecl
。 在执行#include "api.h"
,插件 DLL 中的导出函数声明如下: void CALL func(void);
.
该解决方案是否在实践中使用? 有不同的方法吗?
不,您不必“确保机器 X 上构建的二进制文件与机器 Y 上其他人构建的 DLL(插件)之间的兼容性,这可能具有不同的操作系统等”,除非二进制 X 构建的操作系统是与构建二进制 Y 的操作系统完全不同。 对于上下文,这是彼此不兼容的操作系统列表:
您无需手动指定任何调用约定。 您甚至不需要考虑任何调用约定。
您的解决方案并未在实践中使用。 所需的不同方法是什么都不做。
对于 x86_64 Windows,默认的 Microsoft x64 ABI 调用约定是全面使用的约定。 这应该默认启用。
对于 x86 Windows,图像有点混乱:大多数 Windows API 调用使用__stdcall
,但__cdecl
是用户定义函数的默认约定。 两者的区别在于前者是被调用者清栈,后者是调用者清栈。
在这种情况下,我会使用__cdecl
,因为这是针对 Windows 的MSVC++和GCC的默认设置。
在 Windows 上看到__cdecl
或__stdcall
吗? 有关这方面的更多信息。
在 Linux 上,您应该始终使用适用于您的体系结构的默认调用约定。 此选项始终是最便携的。
总之,使用默认调用约定应该可以全面使用。 你不应该有任何问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.