So implementieren Sie einen Singleton in einer Anwendung mit DLL

Ich habe eine Anwendung (in MS Visual Studio), die 3 Projekte enthält:

Main (derjenige, der die enthältmain Funktion)Gerät (modelliert ein Hardware-Gerät)config (enthält einige Konfigurationen für beide anderen Projekte)

Das Abhängigkeitsdiagramm lautet also:

Main kommt drauf anGerät, was davon abhängtconfigMain kommt drauf anconfig

Dasconfig Das Projekt enthält einen Singleton, der einige Konfigurationsparameter enthält.

Ich entschied mich, das zu drehenGerät in eine DLL projizieren. Als ich das getan habe, habe ich anscheinend zwei Instanzen des Singleton in derconfig Projekt! Ich denke, dies ist ein klassisches Problem, das eine gute Lösung haben könnte. Wie kann ich das beheben?

Ich habe das Problem mit dem folgenden (relativ kleinen) Code reproduziert. Natürlich gibt es in meinem Fall 30 Projekte, nicht nur 3. Und ich möchte nur 1 DLL erstellen (wenn möglich).

<code>// 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];
}
</code>
<code>// 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';
}
</code>
<code>// 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';
}
</code>

Ausgabe:

Vor der Initialisierung in der Anwendung: eins = 0

Nach der Initialisierung in der Anwendung: eins = 1

Gerät funktioniert: zwei = 0

Nach der Arbeit in der Anwendung: zwei = 2

Einige Erklärungen, was der Code macht und warum:

Hauptanwendung startetDer erste Ausdruck soll nur zeigen, dass der Singleton noch nicht initialisiert istHauptanwendung initialisiert den SingletonDer erste Ausdruck zeigt, dass die Initialisierung funktioniert hatHauptanwendung startet das "Hardwaregerät"Innerhalb der DLL wird der Singleton nicht initialisiert! Ich erwarte, dass es ausgegeben wirdtwo = 2Der letzte Ausdruck zeigt, dass der Singleton in der Hauptanwendung noch initialisiert ist

Antworten auf die Frage(3)

Ihre Antwort auf die Frage