3

如果我在 mac 上的 dll 或 bundle 的上下文中创建一个单例类,则该单例类会被实例化一次并由该 dll 的所有实例使用。我正在使用 dll 作为应用程序的插件。现在我想到了以下事情:如果我使用单例类,它将在插件的多个实例之间共享。然而,这使得有效地管理单例类的生命周期变得困难。我能想到的唯一方法是使用引用计数并在引用计数为 0 时使单例删除其自身。

有没有人对此有更好的想法?有没有什么好方法可以将单例对象限制为 dll 的一个实例?

语言是 c++,但解决方案必须在 windows 和 mac 下工作(这里是一个包)。dll 或 bundle 的规范由应用程序给出,因此这里没有什么可更改的。

4

2 回答 2

1

这是我关于 DLL 和 C++ 的黄金法则。

DLL 内部的代码可以用 C++ 编写,但只能从 DLL 导出 C 函数。但是您可以拥有返回 c++ 接口指针的“工厂”函数

试图从 DLL 中导出每个类的每个方法会变得很麻烦。组件和接口方面的事情。

既然你说 DLL,这意味着 Windows。 COM就是答案。COM是你的朋友。制作一个 COM DLL,你的引用计数问题就基本解决了。使用 ATL 模板库(CComObjectRootEx 和朋友)使实现变得非常容易。使用 COM 导出 C++ 类单例有点棘手。最简单的方法是让 COM 类“包装”单例,然后将所有方法调用转发给真正的单例实例。

现在,如果您不熟悉组件对象模型,学习曲线可能会有点陡峭。(而且大多数参考书在进程外 COM、代理/存根 DLL、自动化、IDispatch 上花费了太多时间——这些都与您的问题无关)。

现在如果你没有时间学习 COM,这里有一个关于如何在没有 COM 的情况下实现 DLL 单例模式的粗略框架。

// singleton.h (consumed by DLL and users of your singleton)
// IMySingleton is an interface class.  It only defines pure virtual methods
class IMySingleton
{
public:
    virtual int DoSomething()=0;
    virtual int DoSomethingElse()=0;

    virtual void AddRef()=0;
    virtual void Release()=0;
};

// returns back an instance of IMySingleton with the refcount already at "1"
// This function gets exported out of your DLL(either via .def file or __declexport attribute)
HRESULT GetMySingletonInstance(IMySingleton** ppMySingleton);
// -------------------------------------



// singleton.cpp (compiled into your DLL - but is NOT exported out of the DLL)
class CMySingleton : public IMySingleton
{
public:
    int m_refcount;
    static CMySingleton* s_pInstance;

    // returns an adref'd instance of the singleton
    static CMySingleton* GetInstance()
    {
        if (s_pInstance == NULL)
        {
           s_pInstance = new CMySingleton(); // refcount at 1
        }
        else
        {
           s_pInstance->AddRef();
        }

        return s_pInstance;
    }

    CMySingleton()
    {
       m_refcount = 1;
       // your initialization code goes here
    }

    ~CMySingleton()
    {
       // cleanup code
    }

    int DoSomething()
    {
        /// your code goes here
        return x;
    }

    int DoSomethingElse()
    {
        /// your code goes here
        return y;
    }
    void AddRef() {m_refcount++;}
    void Release()
    {
        m_refcount--;
        if (m_refcount == 0)
        {
            s_pInstance = NULL;
            delete this;
        }
    }

};

// exported out of the DLL
HRESULT GetMySingletonInstance(IMySingleton** ppSingleton)
{
    *ppSingleton = static_cast<IMySingleton*>(CMySingleton::GetInstance());
}

需要访问单例服务的调用者只需调用一次 GetMySingletonInstance。当他们离开时,他们只是通过在他们拥有的指针实例上调用 Release() 来释放单例实例。

于 2011-02-21T00:42:54.180 回答
0

通常,静态对象不会在应用程序或库的多个实例之间共享。每个应用程序都有自己的地址空间,不能访问其他应用程序的内存。您是否正在使用共享内存或进程间通信?

使用引用计数是一个好主意,有几个所谓的"shared-pointer"库可以帮助您实现它。这是我经常使用的一个实现:http: //www.boost.org/doc/libs/1_45_0/libs/smart_ptr/shared_ptr.htm

于 2011-02-20T23:43:42.663 回答