C++類的動態(tài)組件化技術(shù)_第1頁
C++類的動態(tài)組件化技術(shù)_第2頁
C++類的動態(tài)組件化技術(shù)_第3頁
C++類的動態(tài)組件化技術(shù)_第4頁
C++類的動態(tài)組件化技術(shù)_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

1、C+類的動態(tài)組件化技術(shù)         09-12-29 13:44:00     作者:未知    編輯:studa090420論文關(guān)鍵詞:COM組件接口生命周期C+類ATL組件類C+基類ATL模板基類繼承 論文摘要:在組件化編程的時代,如何復用歷史累積的大量沒有組件特性的C+類?本文從工程的角度對這一問題進行探討,利用現(xiàn)有組件技術(shù),提出了一套將C+類平滑過渡到COM組件的完整解決方案。 1. 問題的提出自從Microsoft公布了C

2、OM(Component Object Model,組件對象模型,簡稱COM)技術(shù)以后,Windows平臺上的開發(fā)模式發(fā)生了巨大的變化,以COM為基礎的一系列組件技術(shù)將Windows編程帶入了組件化時代,傳統(tǒng)的面向?qū)ο蟮能浖_發(fā)方法已經(jīng)逐漸被面向組件的方法所取代。COM標準建立在二進制可執(zhí)行代碼級的基礎上,不論何種工具、語言開發(fā)的組件,只要符合COM規(guī)范,就可復用于VC、VB、Delphi、BC等各種開發(fā)環(huán)境中。COM的語言無關(guān)性將軟件復用的層次從源代碼級推進到了二進制級,復用更方便,也更安全。然而,COM技術(shù)帶來全新的軟件設計和開發(fā)模式的同時,也帶來了新的問題。許多軟件公司在開發(fā)自己的軟件產(chǎn)

3、品過程中,都累積了大量C+類,這些代碼設計精良,功能完備,以面向?qū)ο蟮臉藴蕘頇z驗無可挑剔。然而,這些代碼不支持COM,將無法在COM時代繼續(xù)被復用。如果它們在軟件組件化的趨勢中被淘汰,那對軟件公司和開發(fā)人員來說都是極大的損失。COM專家Don Box曾說過,“COM is a super C+”。這給了我們一個啟示,是否可以實現(xiàn)一種技術(shù),能夠動態(tài)的為普通C+類加上一層COM的封裝呢?這樣,既可以保持這些代碼自身的完整和特性,使它們能繼續(xù)應用于原來的系統(tǒng),也可以在需要作為組件使用的時候,把它們動態(tài)轉(zhuǎn)變成組件,復用于新系統(tǒng)。一個自然而然的想法是,為每一個C+類開發(fā)一個只暴露一個接口的COM組件,將

4、原C+類的每個public方法都對應于該接口的一個方法,接口方法的實現(xiàn)可以簡單的調(diào)用相對應的C+類方法即可。這樣,程序邏輯由原有的C+類控制,但COM層的封裝則由組件提供?;舅悸啡缦聢D所示: 本文就這一技術(shù)展開討論,最終提供一套由普通C+類平滑過渡到COM組件的完整解決方案。我們選用ATL(Active Template Library,活動模板庫,簡稱ATL)作為COM組件的開發(fā)工具,開發(fā)環(huán)境為Visual Studio 6.0。如沒有特殊說明,下文中的“C+類”指沒有組件特性C+類,“C+對象”指C+類的實例;“ATL組件類”指用于包裝的ATL類,“ATL對象”指ATL組件類的實例。2.

5、 用ATL包裝C+類 按上述思路將C+對象動態(tài)組件化后,所得的組件實際上由兩部分組成:ATL組件對象和綁定的C+對象。兩者的生命周期互相牽制,但要保持一致。生命周期的管理是C+類動態(tài)組件化的首要難點。C+類分為兩種,一種是簡單的C+類,一種是集合型的C+類。集合型的C+對象管理一組C+對象,負責其創(chuàng)建和刪除,維護它們的生命周期。下面,分別就簡單C+類和集合型C+類的組件化技術(shù)進行說明,展示解決方案的核心技術(shù)。2.1. 簡單C+類的組件化 為使ATL組件類可以自由調(diào)用C+類的方法,需要:l 為ATL組件類安插一個指針成員變量,指向C+類l 提供ATL對象和C+對象的綁定機制我們可以在ATL組件類

6、初始化時創(chuàng)建一個C+類,用成員變量m_pCPPObj記錄,在析構(gòu)時刪除,從而實現(xiàn)ATL組件類和C+類的天然綁定。但出于靈活性考慮,使得ATL組件對象可以綁定任意C+類的對象,我們?yōu)锳TL組件類添加一個綁定函數(shù)Link2CPPObj(CImplement* pObj)。在ATL組件類的構(gòu)造函數(shù)內(nèi),創(chuàng)建一個C+對象,用m_pCPPObj記錄。如果調(diào)用了Link2CPPObj,則將m_pCPPObj指向的對象刪除,改用傳入的C+對象。在ATL組件類的的析構(gòu)函數(shù)內(nèi),刪除其綁定的C+對象。由構(gòu)造函數(shù)和Link2CPPObj函數(shù)的定義可知,m_pCPPObj指針總是有意義的。簡單C+類組件化的思想如下圖所

7、示: 2.2. 集合型C+類的組件化 集合型C+類的情況有所不同。集合型C+類以數(shù)組(array)、列表(list)、映射表(map)的形式管理其它C+對象。集合對象和它管理的元素對象都被包裝成組件后,集合型ATL對象可能調(diào)用一個“Destroy”方法,期望刪除某一個元素ATL對象;這一操作的實質(zhì)卻是,集合型C+對象的“Destroy”方法被調(diào)用,將元素C+對象刪除了,而元素ATL對象卻不知道。這一操作的結(jié)果導致了元素的ATL對象存在,而其綁定的C+對象卻被刪除的情況,兩者的生命周期出現(xiàn)了不一致。為了解決這個問題,我們需要在C+對象被刪除時,能將ATL對象同時刪除;而在ATL對象的引用計數(shù)為0

8、需要刪除自身時,也能把C+對象刪除??尚械慕鉀Q方案是:l 在C+類中保存一個接口指針,指向綁定在一起的ATL對象;為該接口指針賦值的最佳地點顯然是提供綁定機制的Link2CPPObj函數(shù)內(nèi)部,為此,還需要給Link2CPPObj添加一個IUnknown*參數(shù)l 在C+類的析構(gòu)函數(shù)中,判斷該接口指針是否為空,如果不為空,則Release對接口的引用,引發(fā)ATL對象自身的析構(gòu)現(xiàn)在,技術(shù)方案如下圖所示: 2.3. 內(nèi)部創(chuàng)建的組件和外部創(chuàng)建的組件 集合型C+類組件化后仍然是集合型ATL組件,它可以創(chuàng)建、刪除自己管理的組件。這樣,組件的創(chuàng)建就可能有兩種情況:l 由客戶直接創(chuàng)建l 由客戶調(diào)用集合型組件的接

9、口方法間接創(chuàng)建創(chuàng)建方式的不同導致了組件生命周期管理的復雜性。一般說來,組件的創(chuàng)建者負責維護組件的生命周期。上述兩種情況下,分別由客戶和集合型組件維護被創(chuàng)建組件的生命周期。然而,另有一種情況是,客戶創(chuàng)建了一個組件,然后送交一個集合型組件管理,現(xiàn)在維護組件生命周期的責任就由客戶轉(zhuǎn)交給了集合型組件。我們的解決方案必須提供這樣的健壯性和靈活性,以維護各種情況下組件的生命周期。我們?yōu)锳TL組件類添加一個BOO成員m_bInnerManage,作為組件的維護標識。內(nèi)部維護意味著組件的生命周期由其它組件(集合型組件)維護;外部維護則是由客戶維護。 缺省情況下,組件是外部創(chuàng)建并維護的,在組件的構(gòu)造函數(shù)內(nèi)設置外

10、部維護標識。集合型組件創(chuàng)建元素時,需要為元素分別創(chuàng)建一個C+對象和一個ATL對象,然后調(diào)用ATL對象的Link2CPPObj函數(shù)將兩者綁定在一起,在Link2CPPObj函數(shù)內(nèi)修改維護標識。對于第三種情況,可以在外部創(chuàng)建組件由客戶轉(zhuǎn)交給集合型組件時,在集合型組件相應方法內(nèi)重新設置維護標識。2.4. C+基類 為了對現(xiàn)有C+類的改動最小,我們設計一個基類封裝需要為C+類添加的功能。所有需要動態(tài)組件化的C+類都必須從這個基類派生,以保證動態(tài)組件化中C+對象與ATL對象生命周期的一致。如下圖示:實現(xiàn)代碼如下所示:class CCPP2ATLObjBase    

11、;   CCPP2ATLObjBase ();public:       / IUnknown指針,反指向封裝該CPP類的接口       IUnknown*    m_pAssociATLUnk;protected:       virtual CCPP2ATLObjBase ();CCPP2ATLObjBase:CCPP2ATLObjBase() 

12、60;     / 將IUnknown指針初始化為0       m_pAssociATLUnk = NULL;CCPP2ATLObjBase:CCPP2ATLObjBase()       / CPP類的對象析構(gòu)時,Release對接口的引用       if (m_pAssociATLUnk)       

13、;       m_pAssociATLUnk->Release();然后,修改現(xiàn)有各個C+類,使之從CCPP2ATLObjBase派生,如下面代碼片斷所示:class CImplement : public CCPP2ATLObjBase        ;必須指出的是,在CCPP2ATLObjBase基類中,我們設置的m_pAssociATLUnk變量存在和現(xiàn)有C+類成員命名沖突的問題。但是,考慮到原C+類并沒有組件特性,也應該不會有“IUnknown”型指針,因此,

14、只要各個類的變量命名都按照規(guī)范的命名法,出現(xiàn)這種名字沖突的可能性是極小的。2.5. ATL模板基類 通過以上分析,我們發(fā)現(xiàn),所有的ATL組件類都需要實現(xiàn)一些相同的功能:l 保留一個指向其綁定C+對象的指針l 提供一個Link2CPPObj函數(shù)l 在構(gòu)造函數(shù)中創(chuàng)建一個綁定C+類的對象為了減化編碼,我們定義一個帶參數(shù)的模板基類,實現(xiàn)上述公共功能,模板參數(shù)就是綁定的C+類。然后,所有的ATL組件類都從模板基類中派生。現(xiàn)在的技術(shù)方案如下圖所示:實現(xiàn)代碼如下所示:template <class T>class CCPP2ATLTemplateBase : protected: &#

15、160;     / C+類指針       T*          m_pCPPObj;       / 標識繼承該模板的ATL對象是否由內(nèi)部維護       BOOL     m_bInnerManage;public:  &

16、#160;    /*         模板的構(gòu)造函數(shù),實現(xiàn)如下功能:         1、new一個C+實現(xiàn)類對象         2、缺省情況下,ATL對象由外部維護,將內(nèi)部維護標識設為FALSE         3、將C+類中對ATL接口的反指

17、指針設置為空       */       CAtlCPP2ATLTemplateBase()                     m_pCPPObj = new T;          

18、;    m_bInnerManage = FALSE;              m_pCPPObj->m_pAssociATLUnk = NULL;              /*         析構(gòu)ATL對象時,如果該ATL對

19、象是由外部創(chuàng)建的,         則顯式的刪除C+對象         如果ATL對象由內(nèi)部維護,那么什么事都不用做       */       virtual CAtlCPP2ATLTemplateBase()         

20、60;           if (!m_bInnerManage)                      if (m_pCPPObj)             &#

21、160;              delete m_pCPPObj;                            /*       

22、60; Link2CPPObj函數(shù),負責綁定C+對象和ATL接口         1、刪除構(gòu)造函數(shù)中new的C+對象,而使用外部傳入的C+對象         2、將ATL對象的內(nèi)部維護標識設為TRUE         3、設置C+基類中的接口指針成員         4、因為A

23、TL接口傳送給外部使用,需要增加引用計數(shù)       */       virtual void Link2CPPObj(T* pObj, IUnknown* pUnk)                     ASSERT(pObj != NULL);   

24、           ASSERT(pUnk != NULL);              if (m_pCPPObj)                     dele

25、te m_pCPPObj;              m_pCPPObj = pObj;              m_bInnerManage = TRUE;              m_pCPPObj-&

26、gt;m_pAssociATLUnk = pUnk;              m_pCPPObj->m_pAssociATLUnk->AddRef();       ;然后,每個ATL類都從該模板類派生,如下代碼片斷所示:class ATL_NO_VTABLE CATLXX :        ,   &#

27、160;   / 添加ATL模板基類       public CCPP2ATLTemplateBase<CImplementXX>       3.   C+參數(shù)類型的自動化包裝 在本文的技術(shù)方案中,C+類的public方法與ATL組件接口中的方法一一對應;相應的,C+類中方法的參數(shù)類型也要轉(zhuǎn)換為COM規(guī)范所允許的數(shù)據(jù)類型。在基于COM的自動化(Automation)技術(shù)中,Microsoft提供了一套自動化兼容的數(shù)據(jù)類型

28、VARIANT,定義如下:typedef struct FARSTRUCT tagVARIANT VARIANT;typedef struct FARSTRUCT tagVARIANT VARIANTARG;typedef struct tagVARIANT        VARTYPE                     

29、   vt;       unsigned short                  wReserved1;       unsigned short           &#

30、160;      wReserved2;       unsigned short                  wReserved3;       union        

31、0;      Byte                         bVal;                   

32、;            / VT_UI1.              Short                       

33、iVal;                                / VT_I2.              long   

34、;                       lVal;                           

35、;     / VT_I4.              float                         fltVal;     

36、                         / VT_R4.              double          &#

37、160;           dblVal;                            / VT_R8.         

38、60;    VARIANT_BOOL      boolVal;                           / VT_BOOL.          

39、    SCODE                    scode;                          

40、;  / VT_ERROR.              CY                           cyVal;      &

41、#160;                      / VT_CY.              DATE             

42、;          date;                               / VT_DATE.        

43、      BSTR                       bstrVal;                    

44、0;      / VT_BSTR.              DECIMAL                FAR* pdecVal;           &

45、#160;     / VT_BYREF|VT_DECIMAL.              IUnknown                 FAR* punkVal;        

46、60;        / VT_UNKNOWN.              IDispatch                  FAR* pdispVal;      

47、          / VT_DISPATCH.              SAFEARRAY            FAR* parray;          

48、0;        / VT_ARRAY|*.              Byte                         FAR* pbVal;

49、60;                   / VT_BYREF|VT_UI1.              short              &#

50、160;         FAR* piVal;                     / VT_BYREF|VT_I2.              long  

51、60;                       FAR* plVal;                     / VT_BYREF|VT_I4.  

52、60;           float                         FAR* pfltVal;            &

53、#160;      / VT_BYREF|VT_R4.              double                      FAR* pdblVal;   

54、0;              / VT_BYREF|VT_R8.              VARIANT_BOOL      FAR* pboolVal;           

55、     / VT_BYREF|VT_BOOL.              SCODE                    FAR* pscode;       

56、60;          / VT_BYREF|VT_ERROR.              CY                       

57、60;   FAR* pcyVal;                  / VT_BYREF|VT_CY.              DATE           

58、60;           FAR* pdate;                    / VT_BYREF|VT_DATE.              BSTR &#

59、160;                     FAR* pbstrVal;                / VT_BYREF|VT_BSTR.        

60、60;     IUnknown                 FAR* FAR* ppunkVal;      / VT_BYREF|VT_UNKNOWN.              IDispatch &

61、#160;                FAR* FAR* ppdispVal;     / VT_BYREF|VT_DISPATCH.              SAFEARRAY        

62、    FAR* FAR* pparray         / VT_ARRAY|*.              VARIANT                 FAR* pvarVal; 

63、                / VT_BYREF|VT_VARIANT.              void                 &#

64、160;        FAR* byref;                    / Generic ByRef.              char    

65、0;                    cVal;                             

66、0; / VT_I1.              unsigned short           uiVal;                     

67、60;        / VT_UI2.              unsigned long            ulVal;             &#

68、160;                / VT_UI4.              int                   

69、         intVal;                             / VT_INT.           

70、   unsigned int               uintVal;                           / VT_UINT.  

71、60;           char FAR *               pcVal;                      

72、60;      / VT_BYREF|VT_I1.              unsigned short FAR * puiVal;                         

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論