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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VC++、MFC、COM和ATL的區別C++
- MFC介面庫BCGControlBar v27.0新版亮點:新增SVG影像支援GCSVG
- MFC 程式基本介面配置
- 編寫註冊介面
- react,vue編寫介面文件ReactVue
- 一個基於Java的介面快速開發框架!無需編寫程式碼,透過UI介面編寫介面!Java框架UI
- vs2019 Com元件初探-簡單的COM編寫以及實現跨語言呼叫元件
- MFC介面開發類庫BCG Pro for MFC幫助文件:CBCGPEditCtrl的XML格式XML
- java編寫的介面可以呼叫python嗎JavaPython
- MFC訊息對映
- 【IDL〕編寫程式啟動介面
- MFC 之使用者登入介面
- 編寫一個介面壓測工具
- 遠控介紹及介面編寫
- Storm的wordcount程式碼編寫與分析ORM
- MFC介面套包BCG Pro Edition for MFC正式釋出v27.3|附下載
- MFC介面套包BCGControlBar Pro Edition for MFC正式釋出v28.0|附下載GC
- mfc 讀寫 excel 示例 C++ libxlExcelC++
- 換一種方式編寫 Spring MVC 介面SpringMVC
- 複雜SQL分析和編寫SQL
- 基於順豐同城介面編寫sdk,java三方sdk編寫思路Java
- 154 、MFC中使用者介面執行緒執行緒
- Duilib的使用(優化MFC介面)之 配置專案屬性UI優化
- vs2019 Com元件初探-通過IDispatch介面呼叫Com元件
- MFC下CSocket程式設計詳解(轉)程式設計
- Ace Editor 擴充套件編寫初步(轉)套件
- 【MFC】BROWSEINFO設定路徑,支援記憶上次路徑
- python+flask 編寫一個簡單的登入介面例子PythonFlask
- python+flask編寫一個簡單的登入介面例子PythonFlask
- 尋找寫程式碼感覺(三)之使用 Spring Boot 編寫介面Spring Boot
- 查詢手機號碼是否支援攜號轉網的API介面API
- Qt編寫嵌入式linux輸入法/支援自定義詞語和繁體/支援wayland和watson/純QWidget/介面精美可換膚QTLinux
- Excel 開始支援使用 JavaScript 編寫自定義函式ExcelJavaScript函式
- MFC 捕獲按鈕 按下和抬起 (轉)
- 從零開始系列-Laravel編寫api服務介面:12.編寫swagger3.0 API文件LaravelAPISwagger
- drf序列化用APIView寫編寫5個介面並校驗資料APIView
- 14歲男孩編寫了基於Web的Mac OS模擬介面WebMac
- gRPC 的增刪改查系列之service服務端介面編寫RPC服務端
- 幽默:Java程式設計師編寫的完美對稱加法Java程式設計師