How to create shared library specific singleton in

2019-07-13 04:40发布

问题:

I have a set of plugins for an application which all link to a common base library. The base library defines a singleton which maintains a list of all object constructors in each plugin.

On windows, I can create this base library as a static library and thus a copy of the singleton is placed in each plugin. However on Linux I have a bit of the opposite problem as this fellow.

I've tried the following so far:

  • Build base as shared library (as per the original author)
  • Build base as static with -fPIC
  • Build base as static with -fPIC, explicitly remove -rdynamic in CMake

I would really like to keep the program structure the same as it is now by having the singleton definition reside inside of the base library for each plugin to have it's own instance. I have experimented with moving the definition into each plugin but I'd really like to avoid that. Essentially I want to reproduce what he considers a bug. However he defines his singleton completely in one header file which makes sense to me that each plugin would then have its own instantiation of the class, I on the other hand have the definition of the singleton compiled into the base library.

回答1:

The best solution for you is to do the same thing you do on Windows: compile the base library as an archive (static) library and link it into each of the plugins. (This requires compiling the base library with -fPIC.)

The reason this didn't work: you are not controlling the functions you are exporting from the plugins.

On Windows, unless you explicitly DLLEXPORT a function from the plugin, it remains internal. On Linux, the default is the opposite, and when two shared libraries export the same symbol, the first one loaded wins.

So, here is what you need to do:

  1. Compile base library with -fPIC -fvisibility=hidden
  2. For the specific functions that you do want to export from plugins, add __attribute__((visibility("default"))).

Once you've done this, run nm -D new-plugin.so and compare to nm -D old-plugin.so. You should see that the old plugin exports everything, and the new plugin exports only the functions you marked for export.

Another alternative is to use linker script to control symbol visibility.