Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a singleton across DLL boundary [duplicate]

Tags:

c++

singleton

dll

I have a legacy project which has a singleton class like this:

class Singleton
{
public:
    static Singleton& Instance() 
    {
        static Singleton inst;
        return inst;
    }

    void foo();
};

The project uses a DLL which needs to use the same class (part of the source is shared between the hosting application and the DLL, so the DLL has access to Singleton). However, Instance (naturally) returns a different instance for DLL, and a different one for the hosting application. This obviously causes problems.

Is there a way to use the same instance between the DLL and the hosting process? (let's assume that binary compatibility is not an issue.)

like image 673
Tamás Szelei Avatar asked Jan 24 '14 13:01

Tamás Szelei


2 Answers

One way would be to put an ifdef in your Instance() method so that it behaved differently in your app and dll. For example, have the app one call an exported function on the dll which internally calls the dlls Instance() method. Have the dll version work as originally.

Beware though, unless you make methods like foo() virtual, when the app calls foo() it will call the app's implementation of foo(), and when the dll calls foo() it will call the dll's foo(). This is messy at best and problematic at worst.

The neatest way around this is to make a pure virtual interface which contains the public interface, then have the app get a pointer to this interface class from the dll and use that. This way the app has no code from Singleton and you will save yourself future debug pain.

In a shared header:

struct ISingleton
{
    virtual void foo()=0;
};

DLL_EXPORT ISingleton &GetSingleton();

In Dll:

struct Singleton : public ISingleton
{
    virtual void foo() { /* code */ }
};

ISingleton &GetSingleton()
{
    static Singleton inst;
    return inst;
}

In common code (dll or exe):

GetSingleton().foo();
like image 105
tul Avatar answered Nov 15 '22 21:11

tul


I've solved the same problem (eg. class used within library, in other library and also in main application) by moving the static Singleton inst; into cpp file.

Foo.h
class Foo{
public:
  static Foo *getInstance();
...

Foo.cpp
Foo *Foo::getInstance(){
  static Foo instance;
  return &foo;
}

The static variable is then in one position inside library (so/dll) and everything runs fine. I'm even able to have different header files for export.

like image 23
Libor Tomsik Avatar answered Nov 15 '22 21:11

Libor Tomsik