2014-01-24 61 views
2

我有具有單個類這樣的遺留項目:使用跨DLL邊界的單

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

    void foo(); 
}; 

該項目使用一個需要使用相同的類(源的一部分之間共享一個DLL託管應用程序和DLL,因此該DLL有權訪問Singleton)。但是,Instance(自然地)會爲DLL返回一個不同的實例,併爲宿主應用程序返回一個不同的實例。這顯然會導致問題。

有沒有辦法在DLL和宿主進程之間使用同一個實例? (讓我們假設二進制兼容性不是問題。)

回答

2

一種方法是將ifdef放入Instance()方法,以便它在您的應用程序和dll中表現不同。例如,讓應用程序在內部調用dlls Instance()方法的dll上調用導出的函數。有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(); 
0

常見的解決方案是有另一個dll持有單例,但沒有實現一個靜態成員。例如,請參閱此answer

2

我已經解決了同樣的問題(例如在庫中使用的類,在其他庫和主應用程序中)通過移動靜態Singleton inst;進入cpp文件。

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

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

靜態變量然後在庫(so/dll)中的一個位置,並且一切正常運行。我甚至可以有不同的頭文件導出。

+0

這對我有用。 – zhangxaochen

+0

這不能跨越dll, 我不得不創建一個dll入口點,並返回一個指向該實例的指針。 –