我必须向我的团队解释为什么从DLL导出类不是一个好的解决方案,如果我们计划使用来自不同编译器的DLL。但我无法找到证明。有没有东西像“编译器不应该提供向后兼容性,不同的编译器也可以实现自己的命名导出符号的样式,所以从DLL导出的类只能由同一个编译器使用”? 我知道这是真的,但我怎么能证明这一点?另外,如果你知道我的其他论据,请帮忙!
答案 0 :(得分:2)
以下几点可能会让您觉得有趣/有用,可以告诉您的团队。
不同的编译器以不同的方式破坏C ++名称。这个简单的名称修改问题可以通过显式的.def文件来规避。
需要正确编译器选项的不同结构对齐问题(-mms-bitfields,...)。
潜在异常和内存模型的基本冲突:
MSVC DLL中的new / delete或malloc / free不会与Cygwin newlib new / delete或malloc / free合作。一个人不能释放使用不同的new / malloc在函数中分配的空间。
MSVC DLL引发的异常不会被Cygwin可执行文件捕获,反之亦然。
缓慢的GNU SJLJ异常模型(在GCC-3.x及更早版本中使用)与MSVC ++模型兼容,但是新的DWARF2模型(将由GCC-4.x使用) ,将是不相容的。
给出了一个更完整的解释here,我无耻地复制了上述内容。看到你使用MinGW,这应该是非常相关的。
另外,如果您还没有这样做,请查看this SO question的讨论。
答案 1 :(得分:2)
不同的编译器使用不同的运行时库。 std::string
,std::vector<int>
,std::shared_ptr
都有不同的实现。类具有不同的布局(对齐和打包只是布局的一部分)。如果在任何地方甚至只有一个inline
函数,以及在需要分配内存时创建对象,那么关于这种布局的假设会被烘焙到两个模块中。
C ++有一个定义规则的原因,一旦你开始混合编译器,甚至不同的编译器选项,就违反了该规则。
这些是可以安全分享的东西:
请注意,这些都不需要dllexport
。只包含具有相同打包选项的相同头文件就足够了,因为函数是通过v表找到的,而不是通过DLL导入找到的。
当然,您还希望从DLL导出与C兼容的全局函数,以引导对象的创建。对于将使用__declspec(dllexport)
或模块定义文件。此外,我建议extern "C"
用于这些全球出口。
我强烈建议您阅读&#34;组件对象模型&#34; (COM),它有各种其他名称,如DCOM,ActiveX等。你不需要使用所有相同的机制,这会变得相当复杂,但试着至少理解&#34 ;仅与虚拟功能接口&#34;和&#34;引用计数与自我释放&#34;随着&#34;继承图由对象本身遍历&#34;方案提供了混合不同语言和编译器的能力。 (旁注:COM的存在是v-table-only类兼容的原因,因为COM是v-table布局的Windows标准。它与Windows一样接近ABI。)
答案 2 :(得分:0)