繁体   English   中英

从另一个编译器导出的DLL加载类

[英]Loading classes from DLL that was exported by another compiler

如果我们计划从不同的编译器使用该DLL,我必须向我的团队解释为什么从DLL导出类不是一个好的解决方案。 但我找不到证明。 标准中是否存在诸如“编译器不应提供向后兼容性,不同的编译器也可以实现自己的命名导出符号的样式,因此从DLL导出的类可以被同一编译器使用”的东西? 我知道这是真的,但是我怎么证明呢? 另外,如果您知道我的其他说法,请帮忙!

您可能会发现以下几点有趣/有用,可以告诉您的团队。

  • 不同的编译器对C ++名称的处理方式不同。 通过显示的.def文件可以解决此简单的名称处理问题。

  • 需要正确的编译器选项(-mms-bitfields,...)的不同结构对齐问题。

  • 基础异常和内存模型的根本冲突:

    • MSVC DLL中的new / delete或malloc / free不会与Cygwin newlib new / delete或malloc / free合作。 根本无法释放使用其他new / malloc在函数中分配的空间。

    • Cygwin可执行文件不会捕获MSVC DLL引发的异常,反之亦然。

    • 慢速GNU SJLJ异常模型(在GCC-3.x和更早版本中使用)与MSVC ++模型兼容,但是新的DWARF2模型(将由GCC-4.x使用)将不兼容。

这里给出更完整的解释,从这里我无耻地复制了上面的内容。 看到您使用MinGW时,这应该非常相关。

另外,如果您还没有这样做,请查看有关此SO问题的讨论。

不同的编译器使用不同的运行时库。 std::stringstd::vector<int>std::shared_ptr都有不同的实现。 类具有不同的布局(对齐和打包仅是布局的一部分)。 如果甚至在任何地方甚至只有一个inline函数,以及在需要分配内存的对象创建时,关于此布局的假设都会纳入两个模块。

C ++具有一个定义规则是有原因的,一旦您开始混合使用编译器,甚至使用不同的编译器选项,就会违反该规则。

这些是可以安全共享的东西:

  • 只要您注意将deallocator分配给分配器,就可以使用标准布局的纯数据类。 您不能跨库边界释放。 另外,包装的两侧也应相同。
  • 纯虚拟基类,仅包含纯虚拟实例成员函数。 没有实例数据,也没有静态内容。 接口之间没有继承。 并且仅允许将具有实现接口的具体子类的模块在接口指针之间进行强制转换。

请注意,这些都不要求dllexport 仅包含具有相同打包选项的相同头文件就足够了,因为通过v表而不是通过DLL导入可以找到函数。

当然,您还希望从DLL导出与C兼容的全局函数,以引导对象的创建。 对于那些__declspec(dllexport) ,或模块定义文件。 我也建议将extern "C"用于这些全球出口。

我强烈建议您阅读“组件对象模型”(COM),它以其他各种名称命名,例如DCOM,ActiveX等。您不需要使用所有相同的机制,因为它们会非常复杂,但是尝试至少了解“仅具有虚拟功能的接口”和“具有自重新分配的引用计数”以及“对象本身继承了继承图”方案如何提供混合不同语言和编译器的能力。 (附带说明:COM的存在是仅v-table类兼容的原因,因为COM是Windows的v-table布局标准。它与Windows到ABI的距离非常近。)

嗯。我以为只有扩展的dll才能加载c ++类,而扩展的dll是针对MFC的,所以只有visual studio才能使我猜测。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM