COM 学习小记录
COM組件程序:模塊,它可以是 動(dòng)態(tài)連接庫(DLL) && 可執(zhí)行程序(EXE),稱為 進(jìn)程內(nèi)組件(in-of-process component) && 進(jìn)程外組件(out-of-process component)。
COM對(duì)象:建立在二進(jìn)制可執(zhí)行代碼級(jí)的基礎(chǔ)上,因此COM對(duì)象是語言無關(guān)的,這一特性使得使用不同編程語言開發(fā)的組件對(duì)象進(jìn)行交互成為可能。
COM標(biāo)準(zhǔn):規(guī)范 && 實(shí)現(xiàn)。規(guī)范:定義了組件和組件之間的通信機(jī)制,不依賴于特定的語言和操作系統(tǒng);實(shí)現(xiàn):COM庫,COM庫為COM規(guī)范的具體實(shí)現(xiàn)提供了一些核心服務(wù)。實(shí)現(xiàn)包括一些核心的系統(tǒng)級(jí)代碼,這部分核心代碼使得對(duì)象和客戶之間可通過接口在二進(jìn)制代碼級(jí)進(jìn)行交互 。
標(biāo)志對(duì)象:每個(gè)對(duì)象用一個(gè)128位GUID來標(biāo)識(shí),稱為CLSID(class identifier,類標(biāo)識(shí)符或類ID),用CLSID標(biāo)識(shí)對(duì)象可以保證(概率意義上)在全球范圍內(nèi)的唯一性。只要系統(tǒng)中含有這類COM對(duì)象的信息 && 包括COM對(duì)象所在的模塊文件(DLL或EXE文件) && COM對(duì)象在代碼中的入口點(diǎn),客戶程序就可以由此CLSID來創(chuàng)建COM對(duì)象。
標(biāo)志接口:COM模型中,對(duì)象本身對(duì)客戶來說是不可見,客戶只能通過接口請(qǐng)求服務(wù)。每一個(gè)接口都由一個(gè)128位的全局唯一標(biāo)識(shí)符(GUID,Globally Unique Identifier)來標(biāo)識(shí),客戶通過GUID獲得接口的指針,通過接口指針調(diào)用相應(yīng)的成員函數(shù)。
使用服務(wù):客戶成功創(chuàng)建對(duì)象后,它得到一個(gè)指向?qū)ο竽硞€(gè)接口的指針,因?yàn)镃OM對(duì)象至少實(shí)現(xiàn)一個(gè)接口,所以客戶就可以調(diào)用該接口提供的所有服務(wù)。
COM庫:一般不在應(yīng)用程序?qū)訉?shí)現(xiàn),而在操作系統(tǒng)層次上實(shí)現(xiàn),因此一個(gè)操作系統(tǒng)只有一個(gè)COM庫實(shí)現(xiàn),而且COM庫的實(shí)現(xiàn)必須依賴于具體的系統(tǒng)平臺(tái),尤其是系統(tǒng)底層的一些標(biāo)準(zhǔn)。庫可以保證所有的組件按照統(tǒng)一的方式進(jìn)行交互操作,使我們?cè)诰帉慍OM應(yīng)用時(shí),可以不編寫為進(jìn)行COM通信而必需的大量基礎(chǔ)代碼,而直接利用COM庫提供的API進(jìn)行編程,加快了開發(fā)速度。
COM對(duì)象特性:封裝性 && 重用性 && 多態(tài)性。但這種多態(tài)性需要通過COM對(duì)象所具有的接口才能體現(xiàn)出來,就像C++對(duì)象的多態(tài)性需要通過其(virtual)函數(shù)才能體現(xiàn)一樣。
COM接口規(guī)范:接口是包含了一組函數(shù)的數(shù)據(jù)結(jié)構(gòu),這組成員函數(shù)是組件對(duì)象暴露出來的所有信息,通過這組數(shù)據(jù)結(jié)構(gòu),客戶代碼可以調(diào)用組件對(duì)象的功能。客戶程序用一個(gè)指向接口數(shù)據(jù)機(jī)構(gòu)的指針來調(diào)用接口成員函數(shù)。接口指針實(shí)際上又指向另一個(gè)指針,這第二個(gè)指針指向一組函數(shù),稱為接口函數(shù)表(虛函數(shù)表),接口函數(shù)表中的每一項(xiàng)為4個(gè)字節(jié)長的函數(shù)指針,這與對(duì)象的具體實(shí)現(xiàn)連接起來,客戶只要獲得了接口指針,就可以調(diào)用到對(duì)象的實(shí)際功能。對(duì)于一個(gè)接口來說,他的虛函數(shù)表vtable是確定的,因此接口的成員函數(shù)個(gè)數(shù)是不變的,而且成員函數(shù)的先后順序也是不變的;對(duì)于每個(gè)成員函數(shù)來說,其參數(shù)和返回值也是確定的。
接口描述語言:如何描述接口呢?COM接口描述語言是IDL,IDL接口描述語言不僅可用于定義COM接口,同時(shí)還定義了一些常用的數(shù)據(jù)類型,也可以描述自定義的數(shù)據(jù)結(jié)構(gòu)。對(duì)于接口成員函數(shù),我們可以指定每個(gè)參數(shù)的類型,輸入輸出特性,甚至支持可變長度的數(shù)組的描述。IDL支持指針類型,與C/C++很類似。Microsoft Visual C++提供了MIDL工具,可以把IDL接口描述文件編譯成C/C++兼容的接口描述頭文件(.h),從而可以把一種奇怪的東東IDL描述的接口轉(zhuǎn)化C++形式:
IUnknown的定義(IDL):interface IUnknown {HRESULT QueryInterface([in] REFIID iid, [out] void **ppv); ULONG AddRef(void); ULONG Release(void); }IUnknown的定義(C++):class IUnknown {Public: virtual HRESULT _stdcall QueryInterface([in] REFIID iid, [out] void **ppv)=0; virtual ULONG _stdcall AddRef(void)=0; virtual ULONG _stdcall Release(void)=0; }? IUnKnown是:一個(gè)接口,所有COM接口都繼承IUnKnown。定義在WIN32 SDK中的UNKNWN頭文件中。
QueryInterface是:IUnKnown的成員函數(shù),客戶可以通過此函數(shù)來查詢組件是否支持某個(gè)特定的接口,返回一個(gè)指向組件支持的接口的指針,沒有找到則返回NULL。用QueryInterface將組件抽象成由多個(gè)相互獨(dú)立的接口構(gòu)成的集合。
組件的生命期:這一點(diǎn)是通過對(duì)接口的引用計(jì)數(shù)實(shí)現(xiàn)的。客戶并不能直接控制組件的生命期,當(dāng)使用完一個(gè)接口而要用組件的另一個(gè)接口時(shí),是不能將該組件釋放的,對(duì)組件的釋放可以由組件在客戶使用完所有組件之后自己完成。AddRef和Release實(shí)現(xiàn)的是一種名為引用計(jì)數(shù)的內(nèi)存管理技術(shù),當(dāng)客戶從組件獲得一個(gè)接口時(shí),此引用數(shù)值將增加;當(dāng)使用完某個(gè)接口時(shí),組件的引用計(jì)數(shù)值將減1;當(dāng)引用計(jì)數(shù)值為0時(shí)組件可以將自己從內(nèi)存中刪除。AddRef和Release可以增加和減少這一計(jì)數(shù)值。
進(jìn)程內(nèi)組件:進(jìn)程內(nèi)組件和客戶程序運(yùn)行在同一個(gè)進(jìn)程地址空間中,所以一旦客戶程序與組件程序建立起通信關(guān)系之后,客戶程序得到的接口指針指向組件程序中接口的vtable,這vtable包含了所有成員函數(shù)地址,客戶代碼可以直接調(diào)用這些成員函數(shù),所以效率非常高。DLL程序是在運(yùn)行時(shí)刻被客戶裝入到內(nèi)存中的,所以DLL模塊本身也是獨(dú)立的,它并不依賴于客戶程序。
操作DLL程序:有三個(gè)系統(tǒng)函數(shù),LoadLibrary && GetProcAddress && FreeLibrary。一般地,對(duì)于DLL程序的使用過程按照這樣的步驟進(jìn)行:
首先,客戶程序使用LoadLibrary函數(shù)裝入DLL,該函數(shù)返回模塊的實(shí)例句柄,供以后操作該模塊使用。然后,客戶程序可以調(diào)用GetProcAddress函數(shù)獲得DLL中引出的函數(shù)的地址,我們既可以按函數(shù)的序號(hào)(在DEF文件中指定)也可以按函數(shù)的名字來獲取引出函數(shù)的地址,因?yàn)榭蛻舫绦蚝虳LL程序在相同的內(nèi)存地址空間中,所以客戶程序可以直接調(diào)用這些引出函數(shù)。最后,FreeLibrary,把DLL程序卸出內(nèi)存,以便釋放資源。? COM組件不是:COM組件不是DLL,COM只是利用DLL來給組件提供動(dòng)態(tài)鏈接的能力;COM組件不是一個(gè)API函數(shù)集;COM組件不是類。
創(chuàng)建COM對(duì)象:客戶程序通過調(diào)用CoCreateInstance來創(chuàng)建對(duì)象的一個(gè)實(shí)例,并向想要?jiǎng)?chuàng)建的對(duì)象傳送一個(gè)CLSID。
?DLL:是一種程序動(dòng)態(tài)調(diào)用以及連接的技術(shù),他和組件是完全兩種不同的概念,很多組件都采用這種技術(shù)作為自身的連接方式。
IDispatch:IDispatch的存在是因?yàn)橛行┱Z言不支持虛函數(shù)表vtable,比如vb,asp等,它的主要作用是”接收一個(gè)函數(shù)的名稱并執(zhí)行它“,IDispatch有幾個(gè)函數(shù):
GetIDsOfNames:取一個(gè)函數(shù)的名稱并返回其調(diào)度ID,或稱DISPID Invoke:可以將DISPID作為函數(shù)數(shù)組指針的索引附:
http://blog.csdn.net/l12345678/article/details/1707629
轉(zhuǎn)載于:https://www.cnblogs.com/jiayith/p/3862277.html
總結(jié)
- 上一篇: 另外五个 PHP 设计模式
- 下一篇: Web页面布局方式小结