3つのプロジェクトを含むアプリケーション(MS Visual Studio内)があります。
- main(
main
関数を含むもの) - デバイス(一部のハードウェアデバイスをモデル化)
- config(他の両方のプロジェクトの構成が含まれています)
したがって、依存関係グラフは次のようになります。
- mainはデバイスに依存し、これは構成に依存します
- mainは設定に依存します
構成プロジェクトには、いくつかの構成パラメーターを保持するシングルトンが含まれています。
デバイスプロジェクトをDLLに変換することにしました。これを行ったとき、構成プロジェクトでシングルトンのインスタンスが2つ取得されたようです。これは古典的な問題だと思いますが、これには良い解決策があるかもしれません。では、どうすればこれを修正できますか?
次の(比較的小さい)コードで問題を再現しました。もちろん、私の場合、3つだけでなく30のプロジェクトがあります。そして、(可能であれば)1つのDLLだけを作成したいと思います。
// 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';
}
出力:
アプリケーションで初期化する前:one = 0
アプリケーションでの初期化後:one = 1
デバイスは機能しています:2 = 0
アプリケーションで作業した後:2 = 2
コードの機能とその理由に関する説明:
- メインアプリケーションが起動します
- 最初の印刷は、シングルトンがまだ初期化されていないことを示すためだけのものです
- メインアプリケーションはシングルトンを初期化します
- 最初の印刷は、初期化が機能したことを示しています
- メインアプリケーションが「ハードウェアデバイス」を起動します
- DLL内では、シングルトンは初期化されていません。私はそれが出力することを期待しています
two = 2
- 最後の印刷は、シングルトンがまだメインアプリケーションで初期化されていることを示しています