【问题标题】:How does exporting templated C++ classes from shared library work on Linux?从共享库导出模板化 C++ 类如何在 Linux 上工作?
【发布时间】:2013-09-02 14:20:10
【问题描述】:

在 Windows 下,从 DLL 导出具有 std::vectorboost::shared_ptr 字段的类几乎总是会导致访问冲突。显然,在 Linux 上不是这样,并且可以导入

class Test {
public:
     boost::shared_ptr<SomeObscureClass> data;

     // ...
}

从一个共享库到一个已经链接到 Boost 的程序,它都可以工作......但是如何?

据我了解,在 Windows 案例中崩溃的主要原因是主程序和共享库都有 boost::shared_ptr&lt;SomeObscureClass&gt; 方法的模板实例 - 例如,delete 和静态字段会混淆,这会导致做坏事。

但在 Linux 上它显然可以正常工作!我见过至少五个不同的 C++ 库,它们是在 Linux 上开发的,它们内置在共享库中,并且有 std:: 字段,显然不会遇到任何问题。它是如何工作的?

【问题讨论】:

  • 你提到的windows行为并不完全正确。只要使用 /MD(d) 选项,就可以导出包含 std 组件的类。这会动态链接 c++ 运行时,而不是将其编译到您的代码中。 Linux 行为类似,需要链接到 .so 运行时
  • boost::whatever 不在 VS 运行时,它会导致问题。无论如何,运行时不能在其中实现例如boost::shared_ptr&lt;SomeObscureClass&gt;::operator*,因为它不知道SomeObscureClass
  • 您可以使用macros编译boost库来控制导出的接口。问题在于符号可见性而不是操作系统的某些限制。经验法则是,如果您导出资源获取函数,则还必须导出相应的清理函数。

标签: c++ linux boost shared-libraries


【解决方案1】:

与模板实例化相关的符号与其他符号没有任何不同。

在 Linux 上,所有未明确设为私有的符号都会导出共享库,因此进程将仅使用“第一个”库提供的符号(如果您想要共享库,您可能需要多注意您的选项使用主可执行文件提供的符号,但也可以)。您可以将符号明确设为私有,并在需要时使用它提供的共享库;过去你必须使用链接器脚本来实现这一点,而现在,gcc 提供了选项和属性来帮助进行细粒度控制。

我的理解(但我不是 Windows 专家,这正是我在类似论坛上看到的内容)是,在 Windows 上,默认设置是相反的,所有未明确公开的符号都是私有的,但您可以解决通过更改符号的属性来解决问题(我不知道这有多容易或多难)。

【讨论】:

  • 嗯。我是否理解正确:例如,如果在根本不使用 Boost 的程序中使用了内部使用 boost::shared_ptr 的共享库,它仍然可以工作,因为其中包含所有需要的模板实例。但是如果程序确实使用了 Boost,那么该库不会使用自己的 Boost 函数,而是使用主程序中的函数?
  • 您很可能会使用共享的 boost 库,而不是在共享库中包含和导出它们。所以在这两种情况下,来自 boost 的符号都将来自 boost 库。可以多次出现的东西(整个程序使用一致的)是生成模板或内联函数之类的东西。 (是的,整个程序必须使用连贯的 boost 库进行编译,这就是为什么您可能希望将一些符号设为私有而不为与接口相关的事物提供内联函数的原因)。
  • 共享库并不难搞定,但无论您使用什么系统,如果您希望库真正可用,则必须将其设计为共享库。遗憾的是,我不知道对这个主题有什么好的介绍。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多