




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第二章 COM對象和接口,主要內(nèi)容,COM對象的概念與特征 接口的定義與標(biāo)識 接口的內(nèi)存模型 接口的特點(diǎn) IUknown接口 引用計(jì)數(shù) 接口查詢 字典組件舉例,COM基礎(chǔ)三個(gè)概念,COM組件 組件:可獨(dú)立發(fā)布的二進(jìn)制組件 在Windows平臺上表現(xiàn)為DLL或者EXE COM對象 通過COM接口提供服務(wù) 符合OO中對象的基本概念 COM接口 客戶與對象之間的協(xié)議,對象實(shí)現(xiàn)COM接口,客戶使用COM接口從而訪問對象,需要思考的一些問題,COM組件 組件的類型:進(jìn)程內(nèi)組件(DLL)、進(jìn)程外組件(EXE) 為方便起見,只討論Windows平臺上DLL類型的組件 COM對象 如何標(biāo)識一個(gè)對象?對象以什么
2、形式存在?客戶如何創(chuàng)建對象? 對象如何暴露接口?一個(gè)或是多個(gè)? COM接口 要求:跨編譯器、跨語言、跨平臺,2.1 COM對象,概念 COM對象是客戶程序與組件程序進(jìn)行交互的實(shí)體。 COM對象包含屬性和方法(或者狀態(tài)和操作): 屬性反映對象的存在,也是區(qū)別于其他對象的要素; 方法是對象提供給外界的接口。 能夠提供服務(wù)(通過COM接口) 對象的實(shí)現(xiàn)由組件完全包裝起來,2.1.1 COM對象的標(biāo)識CLSID,COM組件的位置透明性 客戶程序并不直接訪問COM對象,而是通過一個(gè)唯一的全局標(biāo)識符進(jìn)行對象的創(chuàng)建和初始化工作。 可選的標(biāo)識符方案: 字符串形式:可讀性好,名字沖突的可能性大 定長位數(shù)的整數(shù):
3、如何保證唯一性?(管理組織 / 大隨機(jī)數(shù)) GUID 是COM規(guī)范采取的方案 是一個(gè)128位的隨機(jī)數(shù) 不絕對保證唯一性,但發(fā)生沖突的可能性非常小 例如: 54BF6567-1007-11D1-B0AA-444553540000 ,GUID續(xù),GUID的C/C+結(jié)構(gòu)描述 typedef struct _GUID DWORD Data1; WORD Data2; WORD Data3; BYTE Data48; GUID ; 保證隨機(jī)性的考慮 空間上:網(wǎng)絡(luò)中的計(jì)算機(jī)通常取網(wǎng)卡的地址(唯一的) 時(shí)間上:同一機(jī)器在不同時(shí)候產(chǎn)生的標(biāo)識符總不相同,GUID (續(xù)),產(chǎn)生GUID的工具 Visual C+提
4、供的兩個(gè)工具: UUIDGen.exe :命令行程序 GUIDGen.exe :基于對話框的程序 COM庫提供的API函數(shù) HRESULT CoCreateGuid ( GUID * pguid) ; GUID 與 CLSID CLSID是標(biāo)識COM對象的GUID 二者在結(jié)構(gòu)上完全一致,2.1.2 COM對象與C+對象的比較,層次差異 COM對象建立在二進(jìn)制級的基礎(chǔ)上 C+對象建立在源代碼級的基礎(chǔ)上 封裝特性 COM對象的數(shù)據(jù)完全封裝在對象內(nèi)部,不能直接訪問 C+對象的公有數(shù)據(jù)成員是可以訪問的 可重用性 COM對象的重用表現(xiàn)為包容和聚合 C+對象的重用表現(xiàn)為繼承與組合 多態(tài)性的表現(xiàn)形式不同 C
5、OM對象的多態(tài)需要通過接口來表現(xiàn),2.2 COM接口,基本內(nèi)容 接口定義與標(biāo)識 用C+定義接口 IDL 接口的內(nèi)存模型 接口的特點(diǎn),2.2.2 接口定義和標(biāo)識,定義 是一個(gè)函數(shù)集,以二進(jìn)制的形式給出了從一方到另一方的調(diào)用規(guī)范;函數(shù)的地址封裝在一個(gè)數(shù)據(jù)結(jié)構(gòu)中。 這個(gè)數(shù)據(jù)結(jié)構(gòu)稱為“接口函數(shù)表” 在C+中稱為“虛函數(shù)表”,簡稱vtable 對于一個(gè)接口來說,它的vtable是確定的,即: 接口成員函數(shù)的個(gè)數(shù)是不變的; 其先后順序也是不變的 客戶程序通過一個(gè)指向vtable的指針來調(diào)用接口成員函數(shù),COM接口結(jié)構(gòu),COM接口舉例(C語言),struct IDictionaryVtble; struct
6、 IDictionary IDictionaryVtble * pVtbl ; ; struct IDictionaryVtble BOOL ( * Initialize) (Idictionary * this); BOOL ( * LoadLibrary) (Idictionary * this, String); void ( * FreeLibrary) (Idictionary * this); ;,COM接口標(biāo)識-IID,Interface Identifier 是GUID的一種用法 例如: extern “C” const IID IID_Iunkown = 0 x0000000
7、0, 0 x0000, 0 x0000 0 xc0, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x00, 0 x46 ; 如果客戶程序要使用一個(gè)COM對象的某個(gè)接口,必須知道該接口的IID以及它能提供的方法。,2.2.3 用C+語言定義接口,COM接口結(jié)構(gòu)中的vtable與class的vtable完全一致 因此,用class描述COM接口是最方便的手段 舉例: class IDictionary virtual BOOL Initialize() = 0; virtual BOOL LoadLibrary(String) = 0; virtual void Fr
8、eeLibrary() = 0; ;,類IDictionary的內(nèi)存結(jié)構(gòu),2.2.4 接口描述語言IDL,以O(shè)SF 的 IDL為基礎(chǔ) 基本數(shù)據(jù)類型 與C語言非常接近,包括結(jié)構(gòu)、聯(lián)合、枚舉、typedef等 interface coclass library 可以產(chǎn)生類型庫,舉例,interface IDictionary HRESULT Initialize(); HRESULT LoadLibrary(in string); HRESULT InsertWord(in string, in string); HRESULT DeleteWord(in string); HRESULT Loo
9、kupWord(in string, out string *); HRESULT RestoreLibrary(in string); HRESULT FreeLibrary(); ; VC+的MIDL可以由IDL文件生成C/C+接口描述,IDL的意義,IDL語言無關(guān) 跨語言的中間語言 MIDL.exe產(chǎn)生C+頭文件定義 相當(dāng)于C+定義 MIDL.exe產(chǎn)生TLB類型庫 COM本身提供了一套基礎(chǔ)設(shè)施來解釋類型庫 所有的標(biāo)準(zhǔn)接口都可以在SDK中找到IDL描述,編譯IDL文件,2.2.5 接口的內(nèi)存模型,如果我們用C+實(shí)現(xiàn)字典對象,則類定義為: class CDictionary : publi
10、c IDictionary public : CDictionary(); CDictionary(); public : virtual BOOL Initialize(); virtual BOOL LoadLibrary(String); / private : struct DictWord *m_pData; char *m_DictFilename128; / ;,接口和字典對象的內(nèi)存結(jié)構(gòu)圖,多個(gè)字典對象與接口的內(nèi)存結(jié)構(gòu)圖,不同方法實(shí)現(xiàn)的字典對象與接口關(guān)系,2.2.6 接口的特點(diǎn),二進(jìn)制特性 接口不變性 繼承性(擴(kuò)展性) 多態(tài)性運(yùn)行過程中的多態(tài)性 (lecture over),2.
11、3 IUnkown 接口,所有的COM接口都必須從IUnknown派生,原因在于Iunknown接口提供了兩個(gè)重要的特性: 生存期控制:通過“引用計(jì)數(shù)”來控制 接口查詢:QueryInterface函數(shù) Iunknown的IDL定義: Interface IUnknown HRESULT QueryInterface( in REFIID iid, out void * ppv ) ; ULONG AddRef( void ) ; ULONG Release( void ) ; ,2.3 IUnkown 接口(續(xù)),Iunknown的C+定義: class IUnknown public: v
12、irtual HRESULT _stdcall QueryInterface( const IID,2.3.1 引用計(jì)數(shù),目的:是為了控制對象的生命周期 多個(gè)客戶可以獨(dú)立地控制對象的生存 引用計(jì)數(shù)反映了COM對象被客戶引用的個(gè)數(shù) 引用計(jì)數(shù)是個(gè)整數(shù),從0開始 兩個(gè)操作:增 1 和 減 1 當(dāng)客戶得到一個(gè)指向?qū)ο蟮慕涌谥羔槙r(shí),引用計(jì)數(shù)1; 當(dāng)客戶用完該接口指針時(shí),引用計(jì)數(shù)1; 當(dāng)引用計(jì)數(shù)為0時(shí),表示沒有客戶在使用對象或者接口刪除,2.3.2 實(shí)現(xiàn)引用計(jì)數(shù),引用計(jì)數(shù)多實(shí)現(xiàn)方案的原因 一個(gè)COM組件可以實(shí)現(xiàn)多個(gè)COM對象 一個(gè)COM對象可以實(shí)現(xiàn)多個(gè)COM接口 組件級實(shí)現(xiàn) ? 對象級實(shí)現(xiàn) ? 接口級實(shí)現(xiàn)
13、? 實(shí)現(xiàn)方案比較(參見下頁的圖) 設(shè)置一個(gè)針對整個(gè)組件的全局引用計(jì)數(shù) 所有對象必須一起釋放 計(jì)數(shù)分辨率太粗 為每個(gè)COM對象設(shè)置一個(gè)引用計(jì)數(shù)(折中方案) 為每個(gè)接口設(shè)置一個(gè)引用計(jì)數(shù) 客戶不一定會用到對象的所有接口,造成資源浪費(fèi) 計(jì)數(shù)分辨率太細(xì),實(shí)現(xiàn)引用計(jì)數(shù)的層次(或粒度),重新定義IDictionary,class IDictionary : public IUnknown virtual BOOL Initialize() = 0; virtual BOOL LoadLibrary(String) = 0; virtual BOOL InsertWord(String, String) =
14、0; virtual void DeleteWord(String) = 0; virtual BOOL LookupWord(String, String *) = 0; virtual BOOL RestoreLibrary(String) = 0; virtual void FreeLibrary() = 0; ;,重新定義CDictionary,class CDictionary : public IDictionary public : CDictionary(); CDictionary(); public : virtual HRESULT QueryInterface(cons
15、t IID,部分實(shí)現(xiàn)代碼,CDictionary:CDictionary () m_Ref = 0; / . initialize ULONG CDictionary:AddRef () m_Ref +; return (ULONG) m_Ref; ULONG CDictionary:Release () m_Ref -; return (ULONG) m_Ref; ,客戶控制引用計(jì)數(shù)的基本規(guī)則,1、客戶創(chuàng)建了組件對象并獲得了第一個(gè)接口指針后,引用計(jì)數(shù)應(yīng)該為1( 0+1 1) 2、在客戶程序中,當(dāng)把接口指針賦給其它變量時(shí),應(yīng)該調(diào)用AddRef,使引用計(jì)數(shù)增1; 3、在客戶程序中,當(dāng)一個(gè)接口指針
16、被用完之后,應(yīng)該調(diào)用Release,使引用計(jì)數(shù)減1;,客戶代碼舉例,IDictionary * pIDictionary = CreateObject(CLSID_Dictionary, IID_Dictionary); if( pIDictionary = NULL ) return; / reference count is 1 / load the dictionary BOOL retValue = pIDictionary-LoadLibrary(eng_ch.dict); if (retValue = FALSE) pIDictionary-Release(); return; .
17、 IDictionary *pIDictionaryForWord = pIDictionary; pIDictionaryForWord -AddRef(); / Insert or delete some word pIDictionaryForWord -InsertWord(.,.); pIDictionaryForWord -DeleteWord(.); pIDictionaryForWord -Release ( ); . / finally, release dictionary object pIDictionary-Release ( );,2.3.3 使用引用計(jì)數(shù)的規(guī)則,1
18、、函數(shù)參數(shù)中使用接口指針變量 輸入?yún)?shù):一般不用調(diào)用AddRef和Release 輸出參數(shù)或返回一個(gè)接口指針變量: 相當(dāng)于生成了一個(gè)新的接口指針接口指針, 因此,需要調(diào)用AddRef 輸入輸出參數(shù) 如果參數(shù)未被修改,則不用調(diào)用AddRef和Release;否則: 在參數(shù)被修改前,對傳進(jìn)來的原接口指針調(diào)用Release,在參數(shù)被修改之后,對新的接口指針調(diào)用AddRef。,2.3.3 使用引用計(jì)數(shù)的規(guī)則(續(xù)1),2、局部接口指針變量: 指的是用已有的值對局部變量賦值; 可以不調(diào)用AddRef和Release。 3、全局接口指針變量: 作為輸入?yún)?shù)傳給函數(shù)之前,調(diào)用AddRef 函數(shù)返回之后,調(diào)用R
19、elease 4、類成員變量 在類的作用域內(nèi),成員變量相當(dāng)于全局變量,因此用R3.,2.3.3 使用引用計(jì)數(shù)的規(guī)則(續(xù)2),5、當(dāng)以上情況都不合適時(shí),采用下面的一般性規(guī)則: 在順序執(zhí)行過程中,如果要對一個(gè)接口指針變量賦值,則對賦值后的接口指針變量調(diào)用AddRef,并且,如果賦值前的接口指針變量還沒有結(jié)束,則賦值前必須對它調(diào)用Release以便先結(jié)束它的使用。 如果要結(jié)束使用一個(gè)接口指針變量,以后不再用到它了,則調(diào)用Release函數(shù)。 盡量養(yǎng)成遵循規(guī)則的好習(xí)慣,以免出現(xiàn)錯(cuò)誤。 在整個(gè)生存期內(nèi),AddRef與Release一定要配對,否則: 漏掉AddRef,程序出錯(cuò) 漏掉Release,對象永
20、不釋放,2.3.3 使用引用計(jì)數(shù)的規(guī)則(續(xù)3),頻繁調(diào)用AddRef和Release會降低程序運(yùn)行效率 需要靈活運(yùn)用,明顯可以省略時(shí)要省略,比如: IDictionary * pIDictionaryForWord = pIDictionary; pIDictionaryForWord -AddRef(); / Insert or delete some word pIDictionaryForWord -InsertWord(.,.); pIDictionaryForWord -DeleteWord(.); pIDictionaryForWord -Release ( ); ,2.3.4 接
21、口查詢,問題的提出 一個(gè)COM對象可以實(shí)現(xiàn)多個(gè)接口,客戶程序可以在運(yùn)行時(shí)刻對COM對象的接口進(jìn)行詢問,以確定其是否已經(jīng)實(shí)現(xiàn)。但對象的多個(gè)接口之間如何聯(lián)系起來呢? 通過IUnknown接口的QueryInterface函數(shù)解決。 QueryInterface函數(shù)的形式 HRESULT QueryInterface( in REFIID iid, out void * ppv ); 輸入?yún)?shù)iid是欲查詢接口的IID 輸出參數(shù)ppv為查詢得到的結(jié)果接口指針 如果對象沒有實(shí)現(xiàn)iid所標(biāo)識的接口,則ppv為空(NULL) 函數(shù)的返回值是一個(gè)32位的整數(shù),含義為: S_OK,查到了指定的接口,接口指針放
22、在ppv中; E_NOINTERFACE,沒有這個(gè)接口,ppv為NULL; E_UNEXPECTED,發(fā)生了意外, ppv為NULL。,客戶程序如何調(diào)用QueryInterface?,假設(shè)字典組件除了實(shí)現(xiàn)了IUnknown接口外,還實(shí)現(xiàn)了IDictionary接口和ISpellCheck接口,則客戶程序只要得到其中的一個(gè)接口指針,就可以得到另外任何一個(gè)接口指針。下面是具體的例子: /create a new dictionary object, and got the first interface pointer IDictionary * pIDictionary = CreateObje
23、ct(CLSID_Dictionary, IID_Dictionary); if( pIDictionary = NULL ) return; / reference count is 1 / load the dictionary retValue = pIDictionary-LoadLibrary(eng_ch.dict); if (retValue = FALSE) pIDictionary-Release(); return; .,調(diào)用QueryInterface(續(xù)),ISpellCheck *pISpellCheck; HRESULT result = pIDictionary-
24、QueryInterface(IID_SpellCheck, (void *) .,2.3.6 QueryInterface函數(shù)的實(shí)現(xiàn),假設(shè)字典對象類CDictionary的定義如下: class CDictionary : public IDictionary , public ISpellCheck public : CDictionary(); CDictionary(); public : / IUnknown member function virtual HRESULT QueryInterface(const IID,CDictionary的定義(續(xù)),/ IDictionary member function virtual BOOL _stdcall Initialize(); virtu
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 存款資金證明管理辦法
- 新能源車項(xiàng)目立項(xiàng)范文
- 藥品管理使用管理辦法
- 西安積分入學(xué)管理辦法
- 2025年中國銨油現(xiàn)場混裝車行業(yè)調(diào)查研究及投資戰(zhàn)略規(guī)劃研究報(bào)告
- 2025年西式面點(diǎn)師實(shí)操考核試卷(實(shí)操面點(diǎn)制作美食行業(yè)人才需求分析)
- 土木外聘人員管理辦法
- 2025年電子商務(wù)師(中級)職業(yè)技能鑒定試卷:電商內(nèi)容營銷與品牌影響力試題
- 拆機(jī)挽留業(yè)務(wù)管理辦法
- 2025年高壓電工實(shí)操技能考試:高壓絕緣技術(shù)應(yīng)用試題集
- 浙江省2024-2025學(xué)年高二下學(xué)期數(shù)學(xué)學(xué)考模擬考(三)(含答案)
- 電大:理論聯(lián)系實(shí)際談一談如何維護(hù)政治安全?參考答案
- 2025年下半年佛山市圖書館招考工作人員易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 社區(qū)社會工作課件
- 醫(yī)藥代表關(guān)鍵客戶管理策略
- 2025年人教版小學(xué)小升初科學(xué)模擬試卷(含答案解析)
- 浙江省杭州市拱墅區(qū)2025年中考英語一模試卷(含筆試答案無聽力答案、原文及音頻)
- 營運(yùn)客車安全例行檢查規(guī)范
- 出口空運(yùn)知識培訓(xùn)課件
- 小學(xué)少先隊(duì)輔導(dǎo)員培訓(xùn)
- 護(hù)理人力資源配置研究-全面剖析
評論
0/150
提交評論