在DLL边界上使用单例

Tam*_*lei 5 c++ dll singleton

我有一个遗留项目,它具有像这样的单例类:

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

    void foo();
};
Run Code Online (Sandbox Code Playgroud)

该项目使用的DLL需要使用相同的类(部分源代码在托管应用程序和DLL之间共享,因此DLL可以访问Singleton)。但是,Instance(自然)为DLL返回一个不同的实例,为托管应用程序返回一个不同的实例。这显然会引起问题。

有没有一种方法可以在DLL和托管进程之间使用同一实例?(让我们假设二进制兼容性不是问题。)

tul*_*tul 7

一种方法是将 ifdef 放入您的 Instance() 方法中,以便它在您的应用程序和 dll 中表现不同。例如,让应用程序调用 dll 上的导出函数,该函数在内部调用 dll 的 Instance() 方法。让 dll 版本像原来一样工作。

但请注意,除非您将 foo() 等方法设为虚拟,否则当应用程序调用 foo() 时,它将调用应用程序的 foo() 实现,而当 dll 调用 foo() 时,它将调用 dll 的 foo()。这往好了说是混乱的,往坏了说是有问题的。

解决这个问题的最巧妙的方法是创建一个包含公共接口的纯虚拟接口,然后让应用程序从 dll 获取指向该接口类的指针并使用它。这样,应用程序就没有来自 Singleton 的代码,您将避免将来的调试痛苦。

在共享标头中:

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

DLL_EXPORT ISingleton &GetSingleton();
Run Code Online (Sandbox Code Playgroud)

在DLL中:

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

ISingleton &GetSingleton()
{
    static Singleton inst;
    return inst;
}
Run Code Online (Sandbox Code Playgroud)

在通用代码(dll或exe)中:

GetSingleton().foo();
Run Code Online (Sandbox Code Playgroud)