2013-06-27 29 views
1

對於我正在開發的C++庫,我已經看到了基於共享庫的插件系統的優點。只要在初始化時掃描的目錄中的一個共享庫提供該功能,該功能就可供該庫的用戶使用。靜態編譯和鏈接時保留共享庫插件系統的結構

使用dlopen,共享庫將被搜索兩個符號:一個函數返回命名他們實現的功能的字符串,一個創建函數實例化類並返回一個指向basse類的指針。事情是這樣的:

在圖書館一

#include "Instance.hpp" 
extern "C" const char* type() { 
    return "InstanceA"; 
} 
//... class InstanceA definition, inherits from Instance 
extern "C" Instance* create() { 
    return new InstanceA(); 
} 

核心庫將掃描插件目錄,並保持地圖與字符串> pointerToCreateFunction以創建新實例。

這真的很方便,而且是非常標準的事情。如果用戶代碼嘗試實例化一個InstanceX,但沒有共享庫實現該類型,則會給出錯誤,所有內容都可以正常工作。

但是這個框架也將用於iOs開發,而App Store不允許加載第三方共享對象。即使加載靜態鏈接插件的庫的自包含版本,我也想保留這個模塊化插件結構。請注意,在項目管理級別,這與在CMake中定義一個創建插件的靜態版本並將其靜態鏈接的變量一樣簡單。這也會排除代碼的動態加載部分。

我缺少的是如何顛倒機制:雖然對於共享對象,核心庫將利用文件系統來了解可以使用的實例類型,但我不知道如何「註冊「他們沒有改變大部分代碼,也沒有進入靜態初始化失敗。貌似有,唯一的辦法是subsituting,掃描類型,並通過包括所有可能的頭並具有很大的開關一樣

Instance* theInstance; 
if (instanceRequired == "instanceA") 
    theInstance = new InstanceA(); 
etc etc... 

的創建函數你有辦法避免,包括任何想法的代碼所有標題,並且每次添加新實例時必須更改Core中的代碼?

+0

我會用靜態初始化(慘敗)的路線。 –

+0

但是大多數情況下,這是失敗的 –

+1

你的意思是在一些模板機制中註冊到Core中的地圖(有很多)?我怎麼知道地圖是在我的模板是 –

回答

0

我通過那些在ctor中調用註冊的討厭的靜態對象來做這樣的事情。

通過使地圖本身成爲本地靜態來避免排序問題,因此無論它來自何處,都會在第一次客戶端調用時構建。 (線程和類似的問題被限制線程啓動,直到-主要時間躲閃,到那個時候所有重要的事情是被迫。)


class RegMap; // the registry 
RegMap& GetRegistry(); // the singleton access function; you can make a separate const/nonconst version or provide another wrapper for registering 

// implementation in core.cpp: 
RegMap& GetRegistry() 
{ 
    static RegMap m; 
    return m; 
} 

//in client ctor: 
GetRegistry().Register(key, func); 
+0

之前實例化的,所以,討厭的靜態對象=模板實例化,調用register的構造函數?我想我應該嘗試一下,但注意.o文件不鏈接,除非明確引用,使用鏈接器選項,請參閱 http://stackoverflow.com/questions/9549714/trying-to-force-static-object-初始化 –

+0

某些類與ctor,是的,'模板'部分是可選的,但可以得心應手 –

+0

你可以舉個例子嗎?如果映射對於Core lib是本地的,那麼我可以肯定它會在第一次註冊時創建,或者如果沒有人註冊,將會被核心代碼發現爲空,導致沒有插件被鏈接? –