從C++開始演進

 

轉自 http://blog.csdn.net/zhuweisky/article/details/83259

我們要解決的問題是複用問題,我們的目標:

(1)       當被複用的軟件升級時,客戶程序不需要重新編譯。

(2)       被複用的軟件應該容易擴展和升級。

(3)       在客戶能正常使用複用組件功能的基礎上,組件向客戶暴露儘可能少的信息。

(4)       儘可能是客戶使用組件更加方便,將許多繁瑣複雜的工作從客戶端轉移到組件內部。==》所有可以在組件內部完成的事情,決不在組件外部完成。

 

COM的核心在於:接口。它解決了複用時兩個主要的問題:

(1)       不同的編譯器對具體技術的不同實現問題和名字改編問題。首先,客戶程序源代碼中僅僅需要引入接口定義,而不同的編譯器對同一接口的VTBL的結構安排是一樣的,所有的組件功能的調用都通過同樣的VTBL來中轉。其次,由於用戶通過接口來調用組件的功能,而不需要其它導出函數,所以沒有名字改編的問題了。

(2)       組件僅僅導出接口,而不是導出類,避免了因組件中的類的大小發生變化而客戶程序不重新編譯而繼續運行時產生運行錯誤的問題。

 

 

 

從C++開始演進:

1.C++程序有兩種複用方式:

(1)源碼複用:

即客戶程序直接得到A.h文件和A.CPP源代碼,將其添加到客戶程序中,然後對所有代碼進行編譯,鏈接。

問題:首先,當客戶機器上有三個正在運行的應用都複用了A時,那麼內存中將會有三份同樣的代碼。其次,當A進行升級或修改時,必須將所有源碼再次分發給所有的客戶,並且所有的客戶程序都必須重新編譯。

(2)目標碼複用:

a.  靜態庫:客戶得到A.h文件和相應的靜態庫文件(主要由.obj構成),然後編譯客戶代碼,並且與鏈接所得到的靜態庫文件。

問題:同上面一樣,只是當A.h不變時,客戶程序只需要重新鏈接即可。

b.  普通DLL:客戶需要知道DLL導出的函數簽名和導出的類的結構,然後就可以在運行時裝載DLL,並調用其中的功能。

問題:主要是各個編譯器對同問題的處理不同,如不同的編譯器對同一簽名的函數的導出名――即名字改編,就可能不一致。

 

以上的所有方式都有一個潛在的假設:那就是開發源碼的編譯器和所有客戶所使用的編譯器是一樣的,而現實中不可能這樣。由於不同的編譯器對導出函數名、導出類的佈局可能不一樣,所以上面三個基本的重用都難以成立,更不要說對升級的支持。

 

2.普通DLL

   上面提到了普通DLL的一些問題,暫時先放下那個問題,還有一個很重要的問題,假設A.dll導出了一個類CA,某個客戶程序使用這個DLL導出類CA工作得很好。這之中,客戶需要知道DLL中類的聲明結構。客戶程序中有類似如下代碼:

        CA* aa  =  new CA() ;

但是當A.dll爲了增強功能升級爲AA.dll時,其所導出的那個類CA個頭變大了。當客戶採用AA.dll代替A.dll後,再次運行,就會出現錯誤。這是因爲,客戶程序並沒有重新編譯,所以它仍然用sizeof(原CA)的空間去容納一個變大後的CA對象,當然就出現錯誤了。

(1)解決這個問題的一個方案是採用一個句柄類,這樣一來無論CA的大小怎麼變,這個封裝CA*的句柄類的大小永遠不會變。==》爲每一個導出類實現一個句柄類是很繁瑣的。

(2)另一個解決方案:不在客戶程序中創建DLL中的類的對象,而是將創建對象的工作從客戶端移到DLL內部,DLL只需導出另外一個被客戶方法,該方法創建一個對象,並返回這個新建對象的指針。

 

 

3.1/2COM DLL

需要說明的是,不同的編譯器對一個接口(該接口不含純虛析構函數,因爲不同的編譯器對純虛析構函數指針在vtbl中安放的位置不一樣)的vptr和vtbl是一致的。所以考慮將接口從實現中完全分離開來。結合上面的2(2)客戶端就不需要知道DLL中複用類聲明的結構了,而只需要所使用的接口的聲明結構。

 

4.3/4 COM DLL ==》DLL中的類從多接口繼承

客戶程序在對向上轉換時2(2)返回的指針作向上轉換時,會使用RTTI,但是RTTI是與編譯器相關的,所以,再一次,將這種向上轉換的動作移到DLL中,讓DLL再次導出一個函數來執行這種轉換並返回適當的指針。

 

5.4/5COM DLL

從4後,客戶就可以得到指向同一個實體的多個接口型的指針,這樣對多個指針執行delete操作,將會導致運行時錯誤,並且客戶必須記住哪個指針對應哪個對象,並保證對每個對象僅僅調用一次delete操作。==》再一次,將這種操作從客戶端移到DLL內部,於是產生了引用計數機制。

 

6.COM DLL,COM EXE

    最後規範化所有操作,並提供COM庫對COM組件的支持,且COM庫最爲客戶與COM組件之間的橋樑。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章