我想编写一个可用作插件的库。该库是用C ++编写的,也应该用在C ++代码中。我发现this article描述了如何通过用户可见的纯虚拟接口结构导出c ++类。简而言之,代码如下:
struct VirtualInterface
{
virtual MyExportedFunction() = 0;
}
class MyInterfaceImplementer : public VirtualInterface
{
...
virtual MyExportedFunction(){...}
...
}
extern "C" MyAPI VirtualInterface* Factory(); // The only exported function
该文章的作者在某些时候指出:
无法有效支持COM的假设C ++编译器是 在Windows市场上注定要被遗忘。这就是为什么,如今, 通过抽象接口从DLL中公开C ++类将起作用 可靠地与Windows平台上的每个体面的C ++编译器一起使用。
我是否认为这种导出C ++类的方式依赖于编译器实现并且不能保证按标准工作?如果是,除了通过创建一个导出接口的每个功能的C接口之外,是否有可移植的方式?
答案 0 :(得分:2)
您可以移植导出C ++类/接口on GNU/Linux and BSD because compilers support Itanium ABI:
从GCC 3.2开始,C ++的GCC二进制约定基于一个独立于供应商的书面C ++ ABI,它专门针对64位Itanium,但也包括适用于任何平台的通用规范。这个C ++ ABI也在某些平台上由其他编译器供应商实现,特别是GNU / Linux和BSD系统。我们已经努力提供一个稳定的ABI,它将与未来的GCC版本兼容,但我们可能会遇到一些难以解决的问题。这些问题可能包括不同供应商对C ++ ABI的不同解释,ABI中的错误,或者不同编译器中ABI实现中的错误。当G ++生成可能与C ++ ABI不兼容的代码时,GCC的-Wabi开关会发出警告。
但是,如果C ++标准库中的类在接口中公开,那么API的实现和使用者必须使用相同的C ++库实现:
与C ++编译器一起使用的C ++库包括标准C ++库,其中包含C ++标准中定义的功能以及语言运行时支持。运行时支持包含在C ++ ABI中,但标准C ++库没有正式的ABI。该库的两个实现是可互操作的,如果一个遵循另一个的事实上的ABI,并且它们都使用相同的编译器构建,或者使用符合相同ABI的编译器来进行C ++编译和运行时支持。
当G ++和另一个C ++编译器符合相同的C ++ ABI,但他们通常使用的标准C ++库的实现不遵循标准C ++库的相同ABI时,使用这些编译器构建的目标文件可用于只有当他们使用相同的C ++库时,才能使用相同的程序。这需要在调用未使用常用库的编译器时指定C ++库头文件的位置。
由于上述支持COM的要求,这也适用于Windows编译器。虽然有一个destructors的皱纹:COM不使用析构函数,所以支持COM的两个编译器可能在将析构函数指针放在v表中的位置上有所不同。
答案 1 :(得分:0)
在 Doom 3 游戏中,引擎可执行文件 Doom3.exe 从 gamex86.dll 动态加载游戏玩法。游戏引擎接口完全按照您的描述通过虚拟函数公开(参见 review)。这在 Windows 和 Linux 上运行良好,允许创建 mod(例如 TheDarkMod 曾经那样生活)。
与动态链接相关的常见问题当然适用: