MFC對COM介面編寫的支援分析 (轉)
MFC對COM的支援分析
MFC採用C++中巢狀類定義的方法實現COM介面。
為了簡化其中的編寫。又採用了大量的宏定義。
以下將從巢狀類實現的原始寫法開始,分析MFC中對COM的支援
一、COM概述
1.COM提供了一種簡潔的二進位制使用方法。為了符合COM規範。用VC++編寫的物件(類) 程式碼必須在編譯後,能按照COM規範的格式提供"介面"。
2.關於介面,介面是一個指標,指標指向一個表格,表格內包含了能操作物件的一組的指標。
3.C++類定義結構對介面的支援。
為了支援多型,包含虛擬函式的C++物件都將包含一個指向虛擬函式表的指標,這種結構符合COM介面規範。
而操作同一物件的介面可以有多個。C++類定義中,可以用兩種方案實現多個介面。
一種是多繼承結構,一個類從多個介面類派生。
另一種是巢狀類定義結構。
ATL採用前者,MFC採用後者。
4.除了規範方法外,COM還規範了物件的建立、生存期等。
每個COM物件對應還有一個"類廠"物件,類廠物件中包含CreateInstance(..)成員,負責物件的建立,建立後,介面才有使用的可能。
而包含COM物件的(DLL)中,應包含一個DllGetClass出口函式,此函式供的COM庫呼叫,在DllGetClassObject中,類廠被建立,類廠介面返回給系統COM庫。
COM庫根據類廠介面,呼叫CreateInstance建立COM物件,返回介面給。使用者使用介面呼叫介面成員操作物件。
5.總結
DLL專案中要提供COM物件,需要用C++類的形式定義物件的屬性和行為,但此類對使用者是不可見的,使用者透過介面操作類物件,因此,類的構造過程中,需要提供合適的介面,提供給使用者。
為了和系統的COM庫相,配合,DLL應該提供規定的幾個輸出函式。並提供指定物件的類廠,以及類廠中物件的建立等。
二、用C++類巢狀定義的結構提供類介面。
如果一個類定義包含一組虛擬函式,則其物件在中結構符合介面結構。
故在整個物件的封裝類中,巢狀定義幾個包含特定虛擬函式組合的類,以及巢狀類成員。
巢狀類的結構設定成欲提供介面的結構。(派生自I...)
例:
1.定義部分:
①介面結構的定義(虛擬函式組合)
class ISpellCheck : public IUnknown //介面一 { public : virtual BOOL __stdcall CheckWord(String, String*) = 0; }; class IDictionary : public IUnknown //介面二 { public : virtual BOOL __stdcall Initialize() = 0; ... ... };
②在類定義中,巢狀定義以上介面類派生類及成員。
class CDictionary { ...QueryInterface(...); file://IUnknown需要用到的呼叫。 ...AddRef(); ...Release(); ... ... class XDictionaryobj:public IDictionary //介面定義 { virtual ULONG _stdcall AddRef(); ... ... }m_dictionaryobj; //介面成員 (其記憶體結構包含一個虛擬函式表指標,此正是介面結構所要求的。 ... ... class XSpellCheckobj:public ISpellCheck { virtual ... ... ... }m_spellCheckObj;//介面成員 ... ... }
巢狀類中需要使用原類(CDictionary),故各巢狀類中有成員儲存原類的指標。
③需要定義一個與上類配合的類廠物件類。
2.實現部分
①各成員的實現
②編寫合適的IUnknown 實現
IUnknown其實是在原類中實現的。
在各巢狀類定義中,AddRef,Release,QueryInterface都呼叫原類中定義的公共AddRef、等函式。
QueryInterface函式中,根據傳入介面ID,返回類中介面成員(m_dictionaryobj 等等)的地址。
以上結構可以構造COM介面,但書寫及維護困難。
MFC採用了大量的宏來簡化巢狀類的書寫。由於宏的使用,在形式上看,與訊息對映有些相識,但其實際編碼,還是巢狀類。
③實現類廠。類廠中建立物件。
三、MFC中,介面定義
1.思路
①一個類中,包含多個介面,故包含多個巢狀類,且QueryInterface中要作多次判斷。
可以抽象成為陣列資料型別(對映表),新增介面簡化為新增表項,查詢介面簡化為查表。
②巢狀類的書寫複雜,用宏定義的方法簡化。
③建立通用類廠
2.實現
①在類定義中新增介面對映表(DECLARE_INTERFACE_MAP),實現中新增對映表填表BEGIN_INTERFACE_MAP、END_INTERFACE_MAP等。
表項內容包括 介面標識(IID),介面成員的位置(相對物件起始地址的偏移量)
②巢狀類定義宏BEGIN_INTERFACE_PART、END_INTERFACE_PART_STATIC等。
②類定義中包含通用類廠成員COleObjectFactory factory,以及COM物件識別符號成員guid,這些由宏DECLARE_OLECREATE完成
3.示例:
介面結構定義略。
定義:
class CDictionaryObj : public CCmdTarget //由CCmdTarget派生,CCmdTarget提供了介面相關支援 { DECLARE_DYNCREATE(CDictionaryObj) //動態建立,類廠要動態建立物件,故必需。 ... ... DECLARE_OLECREATE(CDictionaryObj) //新增類廠成員,COM物件標識成員。 DECLARE_INTERFACE_MAP() //新增介面對映表的宣告,以及相關函式的宣告。 //用此表格記錄實現的介面,以及介面的位置等。 //巢狀類的宣告 BEGIN_INTERFACE_PART(Dictionary, IDictionary) //AddRef、Release等的宣告包含在宏中。 INIT_INTERFACE_PART(CDictionary, Dictionary) STDMETHOD_(BOOL, Initialize)(); ... ... END_INTERFACE_PART_STATIC(Dictionary) //第二個巢狀類 BEGIN_INTERFACE_PART(SpellCheck, ISpellCheck) INIT_INTERFACE_PART(CDictionary, SpellCheck) STDMETHOD_(BOOL, CheckWord)(LPOLESTR, LPOLESTR *); END_INTERFACE_PART_STATIC(SpellCheck) ... ... };
實現:
IMPLEMENT_DYNCREATE(CDictionaryObj, CCmdTarget) //介面標識 extern "C" const IID IID_Dictionary = { 0x54bf6568, 0x1007, 0x11d1, { 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ; extern "C" const IID IID_SpellCheck = { 0x54bf6569, 0x1007, 0x11d1, { 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00} } ; //介面對映表的填寫 BEGIN_INTERFACE_MAP(CDictionaryObj, CCmdTarget) INTERFACE_PART(CDictionaryObj, IID_Dictionary, Dictionary) INTERFACE_PART(CDictionaryObj, IID_SpellCheck, SpellCheck) END_INTERFACE_MAP() //類廠實現,guid的賦值。 // {54BF6567-1007-11D1-B0AA-444553540000} IMPLEMENT_OLECREATE(CDictionaryObj, "Dictionary.Object", 0x54bf6567, 0x1007, 0x11d1, 0xb0, 0xaa, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00) //各函式的實現 STDMETHODIMP_(ULONG) CDictionaryObj::XDictionary::AddRef() { y) //宏中定義了pThis指標,有介面對映表中記錄的偏移計算出COM物件的指標,呼叫物件類成員。 METHOD_PROLOGUE_EX_(CDictionaryObj, Dictionar return (ULONG)pThis-> ExternalAddRef(); //呼叫CCmdTarget基類中對IUnknown的實現。 //在被聚合情況下,ExternalAddRef呼叫外部IUnknownd 的實現 //通常情況下,呼叫InternalAddRef. } STDMETHODIMP CDictionaryObj::XDictionary::QueryInterface( REFIID iid, LPVOID* ppvObj) { METHOD_PROLOGUE_EX_(CDictionaryObj, Dictionary) //介面查詢直接呼叫CCmdTarget的實現,其中,透過查介面對映表得知。 return (HRESULT)pThis-> ExternalQueryInterface(&iid, ppvObj); } ... ...
【: history.back()'>回上一頁】
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1004167/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用MFC編寫internet查詢程式 (轉)
- 基於MFC的編寫執行緒快速入門 (轉)執行緒
- MFC登入介面,跳轉到功能介面
- 編寫註冊介面
- MFC中使用者介面元素更新原理 (轉)
- HTML元件(HTMLCOMPONENTS)之四編寫日曆(1)(轉)HTML元件
- HTML元件(HTMLCOMPONENTS)之四編寫日曆(2)(轉)HTML元件
- HTML元件(HTMLCOMPONENTS)之四編寫日曆(3)(轉)HTML元件
- 對MFC封裝Windows通訊API的研究 (轉)封裝WindowsAPI
- SlimPhp框架的使用(二)編寫介面PHP框架
- COM 物件 和 介面 (轉)物件
- 利用Java編寫HTML檔案分析程式(轉)JavaHTML
- CSharp Tips:讓DotNet實現的COM物件支援IObjectSafety介面 (轉)CSharp物件Object
- react,vue編寫介面文件ReactVue
- MFC訊息響應機制分析 (轉)
- (原創)物件導向的系統對接介面編寫。第4篇物件
- (原創)物件導向的系統對接介面編寫。第3篇物件
- (原創)物件導向的系統對接介面編寫。第2篇物件
- 用VB編寫COM+應用時碰到問題? (轉)
- 為什麼C++編譯器不能支援對模板的分離式編譯 (轉)C++編譯
- 用PHP編寫登陸介面PHP
- 排除Delphi5中編寫COM+程式的一個錯誤 (轉)
- MFC介面庫BCGControlBar v27.0新版亮點:新增SVG影像支援GCSVG
- 編寫git commit資訊的最佳實踐GitMIT
- 編譯程式(compiler)的簡單分析編譯Compile
- Java中Comparable和Comparator介面區別分析Java
- VC++、MFC、COM和ATL的區別C++
- java編寫的介面可以呼叫python嗎JavaPython
- 影片轉碼編輯工具:Compressor Mac中文版(支援big sur)Mac
- 我編寫的俄羅斯方塊原始碼,支援單機對戰,可定製方塊數,鍵盤等!!! (轉)原始碼
- mfc版本及其對應vc版本一覽表 (轉)
- (原創)物件導向的系統對接介面編寫。第5篇(完結)物件
- Xamarin iOS教程之編輯介面編寫程式碼iOS
- 遠控介紹及介面編寫
- 編寫一個介面壓測工具
- MFC介面開發類庫BCG Pro for MFC幫助文件:CBCGPEditCtrl的XML格式XML
- 【譯】編寫git commit資訊的最佳實踐GitMIT
- ZWeily的小品文(一)MFC中的檔案讀寫問題 (轉)