當前位置:
首頁 > 知識 > COM編程 深入COM框架以及實現簡單的COM

COM編程 深入COM框架以及實現簡單的COM


一丶我們要理解COM是什麼(為什麼理解)

現在很多人會用com(也就是ALT)但是不知道原理,如果改一點東西,那麼整體的框架重來,因為你不懂改哪裡,如果懂了,那麼遇到問題,那麼就會知道我要怎麼做,是什麼問題了


二丶什麼是COM

COM是微軟公司為了計算機工業的軟體生產更加符合人類的行為方式開發的一種新的軟體開發技術。在COM構架下,人們可以開發出各種各樣的功能專一的組件,然後將它們按照需要組合起來,構成複雜的應用系統。由此帶來的好處是多方面的:可以將系統中的組件用新的替換掉,以便隨時進行系統的升級和定製;可以在多個應用系統中重複利用同一個組件;可以方便的將應用系統擴展到網路環境下;COM與語言,平台無關的特性使所有的程序員均可充分發揮自己的才智與專長編寫組件模塊;等等。 COM是開發軟體組件的一種方法。組件實際上是一些小的二進位可執行程序,它們可以給應用程序,操作系統以及其他組件提供服務。開發自定義的COM組件就如同開發動態的,面向對象的API。多個COM對象可以連接起來形成應用程序或組件系統。並且組件可以在運行時刻,在不被重新鏈接或編譯應用程序的情況下被卸下或替換掉。Microsoft的許多技術,如ActiveX, DirectX以及OLE等都是基於COM而建立起來的。並且Microsoft的開發人員也大量使用COM組件來定製他們的應用程序及操作系統。

好,這是百度的答案,很多人看了懵逼,簡單來說

總結:

1.COM是一種框架,我們可以利用這個框架,實現跨平台開發,比如你開發了一個COM,那麼別的程序一樣使用

2.COM其實是二進位下的可執行的程序,可以給其他的程序使用


實現簡單的COM從介面設計模式開始

什麼是介面模式

1.介面模式就是我們不知道,但是當用戶用的時候,才知道是什麼類型,所以可以是已知的,規範一下介面即可.

簡單來說:

介面模式就是類似於U盤 插入到電腦上,中間的USB的那個介面,只要是支持這個介面的,都可以插入到電腦上

比如硬碟等等.

2.插件模式: 插件模式是未知的,比如用戶怎麼寫你都是不知道的,所以定義好規範,讓用戶一一的實現你的插件的介面即可.

簡單來說:

簡單來說就是為你的程序提供的擴展,如果用戶實現了你自定義的介面,那麼你的應用程序就可以支持這個功能了.所以插件和介面不要搞混


實現簡單的COM以及思路

1.按照上面所說的,我們要實現COM那麼就要有一個介面,這裡我用C++來寫了,

2.在寫的過程中,我會依次的把為什麼這樣寫,不能怎麼寫都會說清楚,最後開發一個跨語言使用的ATL(也就是COM)組件

3.下面的內容可能有點多,最後我會寫總結,可以看下.雖然函數不多,就一個類,但是從底層講起,為什麼這麼做所以比較多.

1.定義介面類

COM編程 深入COM框架以及實現簡單的COM

首先將第一個介面中的函數

QueryInterFace,這個函數是查找我們的介面,根據查找的介面通過第二個OUT參數接受查詢介面的實現類的對象

什麼意思?(GUID下面講解)

其實就是我定義了一個新的介面類,繼承了IUnKnow,這個新的介面類中有自己新添加的功能,而有一個類是實現了這個介面類,通過這個函數,可以找到實現類的對象,進而可以調用裡面的方法(下面講解)

為什麼要這樣寫返回值,以及參數要這樣寫:

想一下,如果我們返回值是void *的話是不是不需要第二個參數了,是不需要第二個參數了,但你保證所有的語言

都會這樣返回嗎,顯然是不會的,所以要統一介面,統一返回值(HRESULT)參數由第二個傳出

AddRef() 引用計數 這個必須加,因為你想,如果我們每次查詢是否存在就new一個對象,那樣是不是太浪費了

所以搞個引用計數

Release();大家可能不同了,為什麼釋放資源要單獨寫一個Release()釋放,這裡請看下面講解


介面的設計原則

1.介面一旦是定義好的,你的函數的順序不能改變 為什麼?

因為介面的設計都是用的指針,都是虛表去查(虛表是什麼,可以補一下C++的基礎,簡單來說就是通過虛函數來調用的)如果一單你的介面的順序改變了,那麼對應的虛表就會改變,

舉個例子:

比如你的插件(也就是咱們現在寫的這個)有一個功能是Add(int n1,int n2,long *Result) (兩個數相加)

你編譯好了你的插件了,我的Client程序就可以使用了,使用的時候正常調用Add,返回的結果也就正確了,

如果有一天你有一個減法,正好放在的Add的前邊,那麼你的Client就會調用減法了,因為以前的那個位置是輸入Add的這樣就會出錯了.

2.參數不能改變

參數也是不能改變的,介面一點定義了,就不要動了.

3.兼容性

什麼是兼容性

比如你的Client是老版本,用你編寫的新插件,你的Add函數沒有變,還是會依次調用你的函數,不影響使用.

但是你要反過來想,當你的Client是新版本的時候,調用你的舊的插件怎麼辦,比如你的舊的插件沒有Sub函數

而你調用了是不是就出錯了.

所以為了保證兼容,我們會新定義一個介面類,讓以前的實現類繼承新的介面類,而新的介面類繼承以前的介面類

偽代碼:

新版本的插件要這樣寫

COM編程 深入COM框架以及實現簡單的COM

老版本的插件是這樣寫

COM編程 深入COM框架以及實現簡單的COM


介面設計的細節問題 (解決為什麼要用Release)

1名稱粉碎

.我們想一下,C語言的函數,看一下二進位或者DLL,是不是都是原本什麼樣子就是什麼樣子

C++的函數有一個語法支持重載了,內部怎麼支持的重載,這就是一個問題

C++為了支持重載,會對你定義的函數做一個名稱粉碎,也就是加了一些額外的符號,比如我們調試中都會遇到一種錯誤叫做,找不到外部符號

不同的編譯器它的名稱粉碎是不一樣的,這個是沒有標準的,你說有重載,這個是標準可以,但是怎麼實現的,沒有標準

所以我們為什麼要定義為純虛函數,這樣你要調用函數就直接通過虛表,去查找了,而不是找你的實現了,所以我們的介面沒有重載,不能寫任何重載的函數

從逆向角度說一下,為什麼不支持重載,因為VC++6.0編譯器,在建立虛表的時候,會根據函數的類型排序,上面的介面原則說了,不能影響順序問題,所以不能寫

2.多重繼承問題

a.多重繼承會影響虛表的,一旦影響了虛表,就改變的介面的不變原則,(虛繼承也是一樣).

b.不能有虛析構,如果你調用虛析構,VC++6.0會傳入一個1,或者一個0(後台傳入的,逆向角度)這個根據這個狀態值去釋放內存.

而GCC是不一樣的,他可以用數組的方式,反正都可以實現,那麼這樣也違反了介面的設計原則了.

總結:

1.不能用多重繼承(父類沒有虛函數可以多重繼承,不影響子類的虛表即可)

2.不能用虛析構,如果釋放內存,則用純虛方法的Release()來釋放內存

3.不能有重載,重載會影響虛表

文章摘自博客園


更多精彩推薦:

IT職業教育:http://www.ujiuye.com/

更多知識學習:http://www.ujiuye.com/zt/webqianduan/?wt.db=lsh11tt

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 IT優就業 的精彩文章:

原來,我看的是廣告,順帶插播電視劇而已
CSS:transition過渡放在偽類中與應用的區別
自製刻度尺-前端簡易實現「信用」界面
Python垃圾回收機制 總結
神奇的函數作用域

TAG:IT優就業 |

您可能感興趣

深入了解SiC MOSFET實現建議和解決方案示例
深入理解 RPC:基於 Python 自建分散式高並發 RPC 服務
深入淺出講解BANCOR演算法
深入了解美國潮流品牌SOME WARE的主理人Brendan Fowler
深入淺出MyBatis:JDBC和MyBatis介紹
深入底層,仿SpringMVC自己寫框架
YAMAHA雅馬哈研發工程師湯山雄太深入解讀最新SURROUND:AI技術
走進OPPO工廠,深入了解爆款旗艦Find X的誕生
加強合作深入電競領域 為ALIENWARE構建完善生態系統
NVIDIA新一代顯卡PCB諜照深入分析:400mm2、GDDR6、USB-C輸出
深入理解JVM—JVM內存模型
深入聊一聊 Spring AOP 實現機制!
何愷明CVPR演講:深入理解ResNet和視覺識別的表示學習(41 PPT)
英檬科技攜手CCE GROUP與音智達,深入合作構建新零售服務生態
AI智慧引擎加持、OPPO R15拍照效果 深入體驗評測
深入OPPO生產車間,了解關於 Find X身上的重大秘密!
XRDC發布AR / VR創新報告 深入了解行業
微軟官方為AMD CES發布會站台 確認雙方將就新一代Xbox主機進行深入合作
關於Sharpay ICO的深入分析
強悍的ROG PHONE來襲,一張圖帶你深入了解