嚴以律己,寬以待人. 三思而后行. GMail/GTalk: yanglinbo#google.com; MSN/Email: tx7do#yahoo.com.cn; QQ: 3 0 3 3 9 6 9 2 0 .
VC里面實現動態對象載入已經不是什么新鮮事情了,很多的plug-in技術就是例子。Unix下,通過動態載入so獲得一個對象也不是什么難事,不過對這個對象的管理就是一件比較麻煩的事情了。一般的需求如下: 有class TMyObj,準確說TMyObj應該是一個接口,根據不同具體情況會有不同的實現,例如 TMyObj1、TMyObj2等等……而這些TMyObj1和TMyObj2分別保存在不同的so當中,需要根據不同的時候load不同的so,建立相應的對象。由于這些對象都擁有TMyObj的接口,所以對于外部來說對這些類的使用就像對TMyObj的使用一樣。 看起來好像比較簡單,只要在so里面引出一個函數:
而函數在so中的具體實現就是建立不同的子類,例如在obj1.so中:
使用的時候只需要動態load入obj1.so,并且找到onCreateObject函數的入口,就可以建立一個具有TMyObj接口的TMyObj1了。 至于釋放對象,一般有兩種方法:方法一: so中包含另外一個函數:
從so中導出該函數,并在刪除對象的時候調用。方法二: TMyObj的析構函數聲明為虛函數,那么從so導出的onCreateObject()建立的對象,直接執行delete刪除就行了,由于析構函數是虛函數,編譯器會正確的調用TMyObj1的析構函數。 當然,方法二是比較簡單而優雅的方法,既然對于C++來說接口就相當于純虛函數,多增加一個析構的虛函數又何妨呢。但是無論使用哪種方法,都要注意一個問題,就是載入的obj1.so的生命周期要比最后一個TMyObj1的生存周期長。即只要內存中還存在TMyObj1對象,obj1.so就要一直在內存中,不能卸載。要保證這個同步,是比較麻煩的事情。下面就說說我的解決方法: 首先,要選擇一個通用的載入so的lib,這個可以參考一下common c++的DSO(在file.h)里面。(不想使用common c++?我也只是說“參考”而已)。這個支持DLL和so,通過成員函數void *operator[](const char *);獲得指定的symbol的入口。 其次,就要選擇一個通用的SmartPtr。這個當然Loki是首選,Loki的SmartPtr的靈活性比boost的smart_ptr強多了,而且Loki也小巧的多。 然后就要實現一個簡單的so的manager,其實應該說是一個動態object的factory:
可以想象這個類干些什么:load就是載入相應的so,然后獲得so中onCreateObject函數的入口,并賦給成員m_pCreator。而createObj就是調用m_pCreator建立對象。不過有所不同的是 m_pCreator所指向的函數形式是void * funcCreate(void ** p),而多出來void **p用處就是可以讓so中的構造函數中產生的exception能夠傳遞出來。這個不能說不是so的麻煩之處,so中函數的exception不能被外部捕獲,所以只好這樣子做了。 現在,關鍵的地方來了,就是要保證這個TObjFactory的生存周期了。選擇Loki的SmartPtr就能派上用場了。 Loki的SmartPtr可以自己選定適用的StoragePolicy,這正是我們需要的,參考DefaultSPStorage,可以做我們的TMySOStoragePolicy:
顯而易見,這樣做的目的就是要保證釋放指針的時候就減少TObjFactory的引用計數。 好了,現在就是主角了:
以后用起來就簡單多了:
說了這么久,都是主程序的調用,而so中應該如何呢?其實也很簡單:
DECLARE_SO_INTERFACE其實是一個為了方便編寫程序而定義的宏:
可以看到除了導出onCreateObject函數以外,還導出了: TMyObj1::onStaticInit用于載入so的時候執行初始化操作; TMyObj1::onStaticDestroy用于卸載so的時候執行清理操作; TMyObj1::getVersion 獲得對象的版本信息 TMyObj1::onObjectName 獲得對象名信息等 可以擴展前面的TObjFactory,實現這些功能。 同理,我們可以做obj2.so:
另外,一個值得討論的問題是:C++由于沒有反射機制,所以無法實現設值注入和構造注入,只能實現接口注入。不過一般來說也已經足夠使用了。
posted on 2006-09-05 13:07 楊粼波 閱讀(836) 評論(0) 編輯 收藏 引用 所屬分類: 文章收藏 、C++
Powered by: C++博客 Copyright © 楊粼波