Register objects in a static library

I implemented a very basic “plug-in system” as part of a static library. Each "plug-in" implements support for a specific image format, for example. GIF, JPEG, etc. In addition, I have a Singleton (a class called PluginManager ) that contains a list of all available plugins.

The tricky part is that I want to disable / enable plugins by adding or removing their source files from the project file. To do this, each plug-in creates a global variable (with different names) and registers the plug-in in the constructor of this class before PluginManager .

Something like this for the JPEG format ...

 struct JPEGPlugin { // constructor will register plugin JPEGPlugin() { PluginManager::Singleton().RegisterPlugin(this); } // plenty of other code ... }; JPEGPlugin jpeg_instance; // instantiate in global scope 

However, while this works theoretically fine, it fails when linking this static library to other code to create an executable. As long as this executable does not gain access to global plugins (for example, jpeg_instance ), the linker does not see the connection (it completely ignores the side effects of the constructor) and does not include the code in the final executable. In other words, the JPEG plug-in is not available in the final application.

I have encountered problems several times over the years, and I have always looked for a network for solutions. Each time I just found pages that basically say that this is a known issue and that I have to live with it.

But maybe someone from SO knows how to make this work?

+7
c ++ plugins static-libraries
source share
4 answers

I don’t know if this was a solution to solve this problem, but we had a similar problem with the static registration of the factory object, and in Visual Studio we solved it by declaring classes related to __declspec (dllexport), this was necessary, although the libraries were not a dll. But without this, the linker would omit unrelated classes.

The registry solution we worked a little differently and did not include dedicated Stack objects. I picked up the details from the CPP block, that is, where I discovered the __declspec iirc approach.

[edit] We also had to #include to declare a registered class from some part of the code.

+2
source share

Since this is a static library, you might consider having the manager register the plugins (instead of the plugins themselves). The header file may specify some preproc character (i.e. JPEG_PLUGIN) that controls whether the dispatcher registers the plugin based on the inclusion of the header:

 #include "JpegPlugin.h"

 void PluginManager :: RegisterPlugins ()
 {
 #idef JPEG_PLUGIN
     RegisterPlugin (& jpeg_instance);
 #endif
 }

JpegPlugin.h does not have to include a JpegPlugin definition. It could be something like this:

 #ifndef JPEG_PLUGIN_HEADER
 #define JPEG_PLUGIN_HEADER

 #if 0 // change this to 1 to use the plugin
 #define JPEG_PLUGIN
 #include "Jpeg_PluginCls.h"
 #endif

 #endif
+2
source share

This is a response to the answer of Harald Sheikh .

I experimented, and it seems that the MSVC ++ 2005 release mode (but not debug mode) will include the /OPT:REF flag in the linker, which, according to the LINK documentation , will remove any unedited characters from the final EXE. And the webpage for __declspec(selectany) seems to indicate that constructors for global objects are not considered as object references (IMHO wrong, but you have it there). Therefore, I assume that this problem "goes away" for debugging collections - is this correct?

So, I think that Harald’s suggestion for using __declspec(dllexport) is a convenient way to mark a symbol as a “link” because it is listed inside the source code. If for some reason you wanted to avoid exporting a character, I suspect you could do the same using the /INCLUDE:mysymbol linker flag, or disable the /OPT:REF flag.

+1
source share

You are welcome:

  • add static lib project as a reference to exe project
  • set both “link library dependencies” and “Use link library dependency as inputs” as true.

See this: config

If Use Link Library Dependency As Input is set to Yes, the project system is linked in .obj files for .lib created by dependent projects. Thus, all characters are retained.

0
source share

All Articles