Library AutoiNEATialization

In some of POCO libraries (Net on Windows, Data back-ends, Crypto, NetSSL …), there is a need for early library initialization. This task has been done so far in a couple of ways (neither elegant) – we either

  • (1) call initialization (repeatedly) from some strategic points in the library (Net, SSL) that we know will get hit early, or
  • (2) mandate early explicit call (un)initialization (Data back-ends) early from user code.

So, the question here is: can we (and, if the answer is yes, how?) improve the current state?

  • Problem: do tasks early at application init or shared library load, ensuring they are executed prior to any other activity depending on them.
  • Examples: Windows network initialization, DB back-end registration with front-end registry …
  • Solution: looks simple at first, then not so simple when the reality of (1) dynamic/static linkage (on Windows in particular), (2) static variable initialization timing/order and (3) dynamic library loading order (e.g. Data and back-end libraries) hits.

At first, one would think this (SQLite back-end with abbreviated names used as an example here) will do the trick:

// Connector.h:
struct SQLite_API SQLiteRegistrator
{

SQLiteRegistrator()
{
SQLite::Connector::registerConnector();
}

~SQLiteRegistrator()
{
SQLite::Connector::unregisterConnector();
}

};

extern "C" struct SQLite_API SQLiteRegistrator sqliteRegistrator;

// Connector.cpp:
SQLiteRegistrator sqliteRegistrator;

Alas, MSVC will disregard your wishes in both static and dynamic library builds when it sees that the registrator is “not used” anywhere. Luckily, there’s a way to force the linkage:

#pragma(comment (linker, "/include:_sqliteRegistrator")

With some ifdef-ing for 64-bit (no underscore decoration) and dynamic exports, it turns out that the task is achievable:

#pragma(comment (linker, "/export:sqliteRegistrator")

So, now we have a way to force initialization without having to explicitly call registerConnector from user code (or peppering library with initialization code).

Details are in GitHub repo (Net and Data back-ends only at the time of this writing).

This modification was tested on Windows, Mac and Linux, static and shared builds; I’m putting a word out to hear comments and make sure I did not miss something important, so suggestions are more than welcome. I’d like to have this in the upcoming 1.5.2.