2010-09-23 32 views
1

我有一個共享庫lib.so包含一個類Foo。我正在動態加載(在UNIX上爲dlopenlib.so。加載後,我想創建一個Foo的實例。
我可以簡單地使用new運營商創建一個Foo的對象,或者我將不得不創建一個導出的工廠方法放在lib.so將爲我創建該對象?是從共享庫中導出類的構造函數嗎?

其實問題是如果Foo的構造函數被導出,並且它可以簡單地用new運算符調用。我認爲UNIX上的共享庫中的所有類和方法都是默認導出的,我不必像在Windows上那樣顯式導出它們。

除了隱藏創建(並可能初始化)Foo對象的方式,在創建共享庫中包含的類的對象時,還有其他什麼原因使用工廠方法嗎?

回答

0

這種方法存在問題。特別是,當爲庫和程序使用不同版本的相同的編譯器時,不能保證類成員函數具有相同的符號名稱。

因此,去與工廠的方法,和不透明的C指針類型:

// .cpp file 
class Foo { ... }; 

// .h file 
struct FooHandle; 

#ifdef __cplusplus 
extern "C" 
{ 
    FooHandle* constructFoo(...); 
    void releaseFoo(FooHandle*); 
    int someFooMethod(FooHandle*, int param1, ...); 
} 
#endif 

導出共享庫時,始終使用C函數和不透明指針類型。

+1

我相信GCC維護一個兼容的C++ API回到版本3.3.6。請參閱http://stackoverflow.com/questions/3718746/g-version-compatibility – 2010-09-23 13:42:49

+0

@Zan:這不會改變問題:具有其他編譯器的用戶將無法導入使用gcc編譯的共享對象。 – 2010-09-23 13:47:54

+2

你說過「*相同*編譯器的不同版本」,這就是我發表評論的原因。 – 2010-09-23 13:58:59

0

基本答案是肯定的。然而魔鬼在細節中。在Windows上,使用Microsoft C++編譯器,所有符號,無論它們是方法,變量等,都不會默認導出爲DLL。您需要明確地導出函數,類和/或全局變量。我相信Borlands編譯器也是如此(我可能是錯的)。

使用GCC時,它曾經是默認情況下導出所有內容的情況,您無法真正控制它。在幾年前,這種情況隨着被添加的屬性而改變(我無法確切記得它被稱爲什麼,但它的工作方式類似於等效的Microsoft __declspec(dllexport))。

因此,如果您定義一個類並將其標記爲導出(但是您選擇這樣做),那麼將會導出它的構造函數。然而,正如前面的招貼畫所提到的,由於C++的特性,符號的名稱會根據您使用的編譯器而變化,並且有時也會根據C++編譯器的版本而變化。這不一定是個問題,它取決於你想如何使用事物,但這確實意味着你必須意識到這一點。

+0

知名度選項和屬性... – Tomek 2010-09-23 19:37:07

相關問題