I feel this issue may have a simple solution that’s just not obvious to me – I have a config class that is used to store various configuration options loaded from an ini file, among other places. In my application, I have a library and client, and 2 configurations – build the library as a DLL and have the client link dynamically, or build them both together as a single binary. So how can I have/use my config object in both the library and client? If I include the config class definition in both, I assume it will give me link errors due to redefinitions.
Share
No, it won’t. Windows DLLs do not respect the one definition rule. Basically, in Windows, ODR stops at the module boundary, i.e., ODR is respected within an executable and within a DLL, but not across them. Whether that’s a good thing or not is not relevant, that’s just how it is. So, you can include the definition of your config class in both the DLL and the executable. However, there will be two separate instances of the singleton (as I assume it is a singleton class, as config classes usually are), one in each module. In that sense, it won’t be a true singleton, at least, not across the modules.
If you want a true singleton across the modules, you’ll have to do a bit more work. You have two choices: master-slave or merging (or a “daisy chain”).
The first option is to designate one module (e.g., the executable) as the module that instantiates (and keeps) the singleton object, and then you pass a pointer to that instance to all the “slave” modules which can then use it via a common interface (so both modules have the same declaration for the config class, but only one module creates it and passes it to the others). It would look something like this:
In the header file “config_class.h”:
In the cpp file “config_class.cpp”:
where, in the above example, you would call setConfigClassInstance from the master module (most likely the main executable) to set the config object for the DLLs, but make sure the DLLs don’t require the config class during their static initialization (loading).
The second option is to either merge or daisy-chain your singletons. In this case, each module creates its own singleton instance, but then, using a similar scheme as above, they pass pointers to each other’s instances, allowing them to be either merged into one instance (cross-linked), or you chain them together (e.g., like a circular linked-list or ring-list) and you dispatch the calls to the appropriate instance.
I think that for your application, the first option is probably the easiest.
N.B.: In non-Windows environments, the situation is entirely different, and none of the above applies.