Initialization not fully run in plugin DLL


#1

I’m relying on initialization to register various classes in a factory singleton. Looks like this:

static Registration<MySubclass> registration("MySubclassName");

This works in my stand-alone app version, but in the plugin DLL, only a few of the Registration constructors are run. I suspect lazy init, since the classes registered are referred to elsewhere in the code, so the compiler knows they must be initialized.

This used to work in the plugin as well (in a released version), but I haven’t touched the code in some time, and have recently upgraded to Visual Studio 2017.

I could simply remove the registration stuff since I don’t really need it, but it would be nice to know if there’s a way I can force all statics to be initialized.


#2

it’s a little tricky. To ensure all translation units are initialised you need to reference them somehow.
For example, for the purpose of linking-in every self-registering class in our static library we reference a function in each translation unit. The function does not need to actually perform any work, and you don’t have to even call it.

How it works: In each relevant cpp file I place an empty function, for convinience it’s name dervives from the filename, e.g.

void my_static_library_init_filename(){}

… (replace “filename” with your actual filename).

Then you need to reference that function from a translation unit that IS definiatly loaded. So then in a central location make a single function that calls all the individual functions…

void initialise_all_translation_units()
{
   void my_static_library_init_filename(){}; // declare it. (avoids need to include header)
   my_static_library_init_filename(); // call it.

  // next file...
   void my_static_library_init_filename2(){}; // declare it. (avoids need to include header)
   my_static_library_init_filename2(); // call it.

// ...ad nauseum...
}

obviously you can avoid the boilerplate somewhat using macros. e.g.

// in each cpp
DECLARE_INIT_STATIC_FILE(filename);

in the init function…
void initialise_all_translation_units()
{
INIT_STATIC_FILE(filename);
INIT_STATIC_FILE(filename2);
INIT_STATIC_FILE(filename3);
// …etc
}

Hope that makes sense,
jeff


#3

Thanks @JeffMcClintock, makes perfect sense. In my case it might be easier to simply hard code my factory function, avoiding the need for any init code.

Any idea how it once worked without explicitly referencing each translation unit?


#4

For us, there was no problem on Windows, only on Mac. We could force all symbols in the library to link with a linker flag (-force_load) but that caused a severe increase in executable size, like 10’s of MB bigger. So it may be you had particular compiler flags active?