Skip to main content

generic singleton and windows dlls solution

Submitted by lorien on
Forum

This will help anyone who has ever been frustrated by trying to export a template singleton from a dll on windows...
[code]
#define Singleton(api,klass,name)class api name {protected: static api klass* mInstance; inline name() {} inline name(const name&) {} inline ~name() {} inline void operator=(const name&) {} inline static void dtor() { if(mInstance) delete mInstance; }public: static klass& instance() { if(!mInstance) { mInstance = new klass; atexit(dtor); } return *mInstance; }}

#define SINGLETON_DATA(name) klass* name::mInstance = NULL
[/code]

You declare a singleton in your code with
[code]

//in a header somewhere

#ifdef MY_DLL_EXPORT
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif

//also in a header somewhere

Singleton(MY_DLL_API,MyClass,MySingleton);

//probably in MyClass.cpp

SINGLETON_DATA(MySingleton);
[/code]

You then use it with
[code]
MySingleton::instance().myMethod();
[/code]

The bottom line is it is (imho) impossible to use template singletons inside dlls on windows then use those singletons in other dlls or exes. Even partial template specialisation doesn't work:

[code]
template
class Singleton;

template
class Singleton
{
...
};

template
class Singleton
{
...
};
[/code]

fails because Singleton and Singleton are completely different types.

Hence my preprocessor hacking.

Hope it is useful

Submitted by lorien on Thu, 07/04/05 - 12:23 AM Permalink

That static variable doesn't need "api" in front of it (it seemed as though it did with mingw, but that was a misunderstanding on my part). The reson why this thing has to be a macro is because you may want to create Singletons in multiple dlls and exes, so the normal preprocessor trick for handling __declspec is useless.

Posted by lorien on
Forum

This will help anyone who has ever been frustrated by trying to export a template singleton from a dll on windows...
[code]
#define Singleton(api,klass,name)class api name {protected: static api klass* mInstance; inline name() {} inline name(const name&) {} inline ~name() {} inline void operator=(const name&) {} inline static void dtor() { if(mInstance) delete mInstance; }public: static klass& instance() { if(!mInstance) { mInstance = new klass; atexit(dtor); } return *mInstance; }}

#define SINGLETON_DATA(name) klass* name::mInstance = NULL
[/code]

You declare a singleton in your code with
[code]

//in a header somewhere

#ifdef MY_DLL_EXPORT
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif

//also in a header somewhere

Singleton(MY_DLL_API,MyClass,MySingleton);

//probably in MyClass.cpp

SINGLETON_DATA(MySingleton);
[/code]

You then use it with
[code]
MySingleton::instance().myMethod();
[/code]

The bottom line is it is (imho) impossible to use template singletons inside dlls on windows then use those singletons in other dlls or exes. Even partial template specialisation doesn't work:

[code]
template
class Singleton;

template
class Singleton
{
...
};

template
class Singleton
{
...
};
[/code]

fails because Singleton and Singleton are completely different types.

Hence my preprocessor hacking.

Hope it is useful


Submitted by lorien on Thu, 07/04/05 - 12:23 AM Permalink

That static variable doesn't need "api" in front of it (it seemed as though it did with mingw, but that was a misunderstanding on my part). The reson why this thing has to be a macro is because you may want to create Singletons in multiple dlls and exes, so the normal preprocessor trick for handling __declspec is useless.