I have an application (in MS Visual Studio) that contains 3 projects:
- main (the one that contains the
main
function) - device (models some hardware device)
- config (contains some configuration for both other projects)
So the dependency graph is:
- main depends on device, which depends on config
- main depends on config
The config project contains a Singleton, which holds some configuration parameters.
I decided to turn the device project into a DLL. When i did this, it seems that i got two instances of the Singleton in the config project! I guess this is a classic problem, which might have a good solution. So how can i fix this?
I reproduced the problem with the following (relatively small) code. Of course, in my case there are some 30 projects, not just 3. And i would like to make just 1 DLL (if possible).
// config.h
#pragma once
#include <string>
#include <map>
class Config
{
public:
static void Initialize();
static int GetConfig(const std::string& name);
private:
std::map<std::string, int> data;
};
// config.cpp
#include "config.h"
static Config g_instance;
void Config::Initialize()
{
g_instance.data["one"] = 1;
g_instance.data["two"] = 2;
}
int Config::GetConfig(const std::string& name)
{
return g_instance.data[name];
}
// device.h
#pragma once
#ifdef _DLL
#define dll_cruft __declspec( dllexport )
#else
#define dll_cruft __declspec( dllimport )
#endif
class dll_cruft Device
{
public:
void Work();
};
// device.cpp
#include "device.h"
#include <iostream>
#include "config.h"
void Device::Work()
{
std::cout << "Device is working: two = " << Config::GetConfig("two") << '\n';
}
// main.cpp
#include <iostream>
#include "config.h"
#include "device.h"
int main()
{
std::cout << "Before initialization in application: one = " << Config::GetConfig("one") << '\n';
Config::Initialize();
std::cout << "After initialization in application: one = " << Config::GetConfig("one") << '\n';
Device().Work();
std::cout << "After working in application: two = " << Config::GetConfig("two") << '\n';
}
Output:
Before initialization in application: one = 0
After initialization in application: one = 1
Device is working: two = 0
After working in application: two = 2
Some explanations on what the code does and why:
- Main application starts
- The first print is just to show that the singleton is not initialized yet
- Main application initializes the singleton
- The first print shows that the initialization worked
- Main application starts the "hardware device"
- Inside the DLL, the singleton is not initialized! I expect it to output
two = 2
- The last print shows that the singleton is still initialized in main application