Hallo,
ich bin gerade dabei ein unter MacOS funktionsfähiges Projekt unter Windows zu kompilieren.
Das Projekt ist Modular in Bibliotheken (unter Win jetzt DLLs) gegliedert. In einer DLL (nennen wir sie mal CommonDLL) befinden sich von allen Komponenten gemeinsam genutzer Code.
Darunter ist u.a. auch ein Singleton-Template
singleton.h
Innerhalb dieser CommonDLL gibt es dann die konkrete Klasse, die als Singleton fungieren soll (ClassXY.h / ClassXY.cpp).
In ClassXY.h wird dann das Singleton aus der Klasse per typedef definiert.
.
Innerhalb der CommonDLL wird dann auf die Instanz per SingletonClassXY::Get() zugegriffen. Das gleiche auch in den Komponenten, die die CommonDLL nutzen.
Das Problem: Jede Komponente hat sein eigene SingletonClassXY-Instanz. Jeder Aufruf von Get() führt in jeder Komponente also dazu, dass eine neue Instanz erzeugt wird.
Lösung:
Der Singleton-Code darf nicht mehrfach erzeugt werden und das geht wohl mit __declspec(dllexport) bzw. __declspec(dllimport). Allerdings habe ich es noch nicht geschafft.
In der ClassXY.h habe ich folgendes hinzugefügt:
In ClassXY.cpp habe ich dann ein
gesetzt.
Allerdings bleibt das Problem nach wie vor bestehen.
edit:
Habs jetzt hinbekommen. Die Änderungen hab ich mal rot hinzugefügt.
Die Prärpozessordirektiven (ab #ifdef EXPORTS ...) müssen irgendwo zentral liegen und entsprechend erweitert werden um das Schlüsselwort "extern" bei Bedarf hinzufügen zu können. Auch das Singleton muss dann mit __declspec(dllexport) gekennzeichnet werden.
Ganz wichtig auch diese Zeile:
EXPIMP_TEMPLATE template class IMEXP Singleton<ClassXY>;
Aber rein aus Interesse: Warum ging das unter MacOS? Ist das shared Library-Prinzip dort anders? Weiß das jemand?
ich bin gerade dabei ein unter MacOS funktionsfähiges Projekt unter Windows zu kompilieren.
Das Projekt ist Modular in Bibliotheken (unter Win jetzt DLLs) gegliedert. In einer DLL (nennen wir sie mal CommonDLL) befinden sich von allen Komponenten gemeinsam genutzer Code.
Darunter ist u.a. auch ein Singleton-Template
singleton.h
Code:
template <class T>
class [COLOR=Red]IMEXP [/COLOR]Singleton
{
public:
static T* Get() {
if(!m_Instance) m_Instance = new T;
return m_pInstance;
}
protected:
Singleton(){}
~Singleton(){}
private:
Singleton(Singleton const&);
Singleton& operator=(Singleton const&);
static T* m_pInstance;
};
template <class T>
T* Singleton<T>::m_Instance=NULL;
#endif
In ClassXY.h wird dann das Singleton aus der Klasse per typedef definiert.
Code:
#include "singleton.h"
class [COLOR=Red]IMEXP [/COLOR]ClassXY
{
//
};
typedef Singleton<ClassXY> SingletonClassXY;
Innerhalb der CommonDLL wird dann auf die Instanz per SingletonClassXY::Get() zugegriffen. Das gleiche auch in den Komponenten, die die CommonDLL nutzen.
Das Problem: Jede Komponente hat sein eigene SingletonClassXY-Instanz. Jeder Aufruf von Get() führt in jeder Komponente also dazu, dass eine neue Instanz erzeugt wird.
Lösung:
Der Singleton-Code darf nicht mehrfach erzeugt werden und das geht wohl mit __declspec(dllexport) bzw. __declspec(dllimport). Allerdings habe ich es noch nicht geschafft.
In der ClassXY.h habe ich folgendes hinzugefügt:
Code:
#ifdef WIN32
#ifdef EXPORTS
#define IMEXP __declspec(dllexport)
[COLOR=Red] #define EXPIMP_TEMPLATE[/COLOR]
#else
#define IMEXP __declspec(dllimport)
[COLOR=Red] #define EXPIMP_TEMPLATE extern[/COLOR]
#endif
#else
#define IMEXP
#endif
//...
[COLOR=Red]EXPIMP_TEMPLATE template class [/COLOR][COLOR=Red]IMEXP [/COLOR][COLOR=Red]Singleton<ClassXY>;[/COLOR]
typedef IMEXP Singleton<ClassXY> SingletonClassXY;
Code:
#define EXPORTS
Allerdings bleibt das Problem nach wie vor bestehen.
edit:
Habs jetzt hinbekommen. Die Änderungen hab ich mal rot hinzugefügt.
Die Prärpozessordirektiven (ab #ifdef EXPORTS ...) müssen irgendwo zentral liegen und entsprechend erweitert werden um das Schlüsselwort "extern" bei Bedarf hinzufügen zu können. Auch das Singleton muss dann mit __declspec(dllexport) gekennzeichnet werden.
Ganz wichtig auch diese Zeile:
EXPIMP_TEMPLATE template class IMEXP Singleton<ClassXY>;
Aber rein aus Interesse: Warum ging das unter MacOS? Ist das shared Library-Prinzip dort anders? Weiß das jemand?
Zuletzt bearbeitet: