如何创build共享库特定的单例实例

我有一套应用程序的插件,都链接到一个共同的基础库。 基础库定义了一个单例,它维护每个插件中所有对象构造函数的列表。

在Windows上,我可以创build这个基础库作为一个静态库,因此单身的副本放置在每个插件。 然而在Linux上,我和这个人有一些相反的问题。

到目前为止我已经尝试了以下内容:

  • 将基础构build为共享库(按照原始作者)
  • 使用-fPIC将基础构build为静态
  • 用-fPIC构build静态的基础,在CMake中显式删除-rdynamic

我真的希望保持程序结构与现在一样,通过让singleton定义驻留在基本库的内部,让每个插件拥有自己的实例。 我已经尝试将定义移入每个插件,但我真的想避免这种情况。 基本上我想重现他认为的一个错误。 然而,他将自己的单例完全定义在一个头文件中,这对我来说是有道理的,即每个插件都有它自己的类的实例化,另一方面我将单例的定义编译到基础库中。

最好的解决方案是在Windows上做同样的事情:将基本库编译为归档(静态)库并将其链接到每个插件中。 (这需要使用-fPIC编译基础库。)

这不起作用的原因:你不控制你从插件导出的功能。

在Windows上,除非您明确从插件中使用DLLEXPORT函数,否则它仍然是内部的。 在Linux上, 默认是相反的,当两个共享库导出相同的符号时,第一个加载成功。

所以,这是你需要做的:

  1. 使用-fPIC -fvisibility=hidden编译基础库
  2. 对于你想要从插件导出的特定函数,添加__attribute__((visibility("default")))

完成此操作后,运行nm -D new-plugin.so并与nm -D old-plugin.so进行比较。 您应该看到旧插件导出所有内容,而新插件导出您标记为导出的功能。

另一种选择是使用链接器脚本来控制符号可见性。