【问题标题】:Using a singleton across DLL boundary [duplicate]跨 DLL 边界使用单例 [重复]
【发布时间】:2014-01-24 13:26:43
【问题描述】:

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

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

    void foo();
};

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

有没有办法在 DLL 和宿主进程之间使用同一个实例? (假设二进制兼容性不是问题。)

【问题讨论】:

    标签: c++ dll singleton


    【解决方案1】:

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

    但请注意,除非您将 foo() 之类的方法设为虚拟,否则当应用程序调用 foo() 时,它将调用应用程序的 foo() 实现,而当 dll 调用 foo() 时,它将调用 dll 的 foo() .这充其量是混乱的,最坏的情况是有问题的。

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

    在共享标头中:

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

    在DLL中:

    struct Singleton : public ISingleton
    {
        virtual void foo() { /* code */ }
    };
    
    ISingleton &GetSingleton()
    {
        static Singleton inst;
        return inst;
    }
    

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

    GetSingleton().foo();
    

    【讨论】:

      【解决方案2】:

      我通过移动静态 Singleton inst; 解决了相同的问题(例如,在库、其他库和主应用程序中使用的类);到 cpp 文件中。

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

      然后静态变量位于库 (so/dll) 中的一个位置,并且一切运行正常。我什至可以导出不同的头文件。

      【讨论】:

      • 这对我有用。
      • 这在 dll 中不起作用,我必须创建一个 dll 入口点,并返回一个指向实例的指针。
      • 为什么迁移到 cpp 有效?
      • @camino 仅当单例已经属于 dll 时才有效。如果单例属于 .exe 和 .dll 共有的静态库,则它将无法工作。答案更重要。你有更多的答案在这里stackoverflow.com/questions/6935541/…
      【解决方案3】:

      常见的解决方案是拥有另一个包含单例但未使用静态成员实现的 dll。例如,请参阅此answer

      【讨论】:

        猜你喜欢
        • 2013-12-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-23
        • 2011-07-03
        • 2017-01-08
        • 2016-11-15
        相关资源
        最近更新 更多