Presentation is loading. Please wait.

Presentation is loading. Please wait.

COM Client/Interface/Object Architecture and Implement 國立交通大學資訊科學系 分散式系統實驗室 謝欣君.

Similar presentations


Presentation on theme: "COM Client/Interface/Object Architecture and Implement 國立交通大學資訊科學系 分散式系統實驗室 謝欣君."— Presentation transcript:

1 COM Client/Interface/Object Architecture and Implement 國立交通大學資訊科學系 分散式系統實驗室 謝欣君

2 COM Client/Interface/Object n COM Client: 直接操作 COM 物件的程式 n COM Object: 提供服務供 COM Client 呼叫 使用之 software component ,通常又稱為 COM Server n COM Interface: 負責溝通 COM Client 與 COM Object, 並且宣告 COM Object 有那些 服務,使得 COM Client 知道 COM Object 有什麼功能

3 COM Interface Architecture n 在 COM 中,Interface 與 Object 的對應關係可 以一對多或多對一,亦即 m:n 的關係 COM Interface1 COM Interface2 COM Object1 COM Object2 可以有許多 COM Object 實作之 可以實作許多 COM Interface

4 COM Interface/Object 繼承機制 n COM Interface 採用介面繼承,且只能有 一個 father n COM Object 採用實作繼承,可以有許多 father( 包括 Interface 、 Object) n COM Interface 在各物件導向語言中,是 一致的觀念, COM Object 則依照程式語 言的特性而有不同的性質

5 父 COM Interface f1(),f2() 子 COM Interface f1(),f2()// 繼承來的 f3(),f4()// 自己訂的 父 COM Interface 之 實作 :COM Object1 f1(),f2()// 必定要實作 子 COM Interface 之 實作 :COM Object2 f1(),f2()// 需重新實作 f3(),f4()// 必定要實作 實作 ( 用 C++ 的繼承 ) 繼承 ( 用 IDL 的繼承 ) 也可繼承 Object1 的 f1(),f2()

6 IUnknown Interface n 提供三個重要的 function:QueryInterface() 、 AddRef() 、 Release() n 所有的 COM Interface 都必須繼承此介面 n in UNKNOWN.H 定義如下 : Interface IUnknown { virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv)=0; virtual ULONG __stdcall AddRef()=0; virtual ULONG __stdcall Release()=0; };

7 QueryInterface 的使用 Void foo(Iunknown* pI) { IX* pIX=NULL; //Define a pointer for the interface //Ask for interface IX HRESULT hr=pI->QueryInterface(IID_IX,(void**)&pIX); if (SUCCEEDED(hr)) //Check return value { pIX->Fx(); //Use interface } 註 : 假設 pI 已知 ( 由 COM API 或 Class Factory 在建立物件時得到 )

8 QueryInterface 的實作 設條件如下 : interface IX:IUnknown{/*…*/}; interface IY:IUnknown{/*…*/}; class CA:public IX,public IY{/*…*/}; 實作如下 : HRESULT __stdcall CA::QueryInterface(const IID& iid,void** ppv) { if (iid==IID_IUnknown || iid==IID_IX) { *ppv=(IX*)this; } else if (iid==IID_IY) { *ppv=(IY*)this; } else { *ppv=NULL; return E_NOINTERFACE; } ((IUnknown*)*ppv->AddRef(); return S_OK; }

9 QueryInterface 的運作 n 實際上 QueryInterface 是在作 Casting 的動作 IX vtbl pointer IY vtbl pointer Instance data for CA IY CA::this (IX*)CA::this (IY*)CA::this QueryInterface AddRef Release Fx Fy IX IY CA Virtual Function Table IY* pC=pA; 會轉成下列程式碼 : IY* pC=(char*)pA+ IY Object CA

10 GUID & IID & CLSID n COM Interface 的識別元為 IID,COM Object 的識別元為 CLSID, 兩者皆用 GUID 的格式,GUID 其實就是 OSF DCE 的 UUID typedef struct GUID { DWORD Data1; WORD Data2; WORD Data3; BYTE Data4[8]; }GUID; typedef GUID CLSID; typedef GUID IID; 註 : 由上述 Microsoft 所定義的結構可知共有 4+2+2+8=16 bytes=128 bits

11 Object Life Cycle Management n 如果一個 function 會傳回新的 COM Interface 指標, 則要呼叫 AddRef() n 如果 copy 了一份 COM Interface 指標, 也要 呼叫 AddRef(), 用完後呼叫 Release() n 在 multi-threaded 的環境下,COM Client 如 果多一個 thread, 則必須呼叫 AddRef(), 結 束時呼叫 Release()

12 Object Life Cycle Management n 如果 COM Interface 指標為全域變數, 在欲 使用之 Block start 處呼叫 AddRef(),end 處 呼叫 Release() A1A2R1R2A3R3 Client 1 Client 2 Client 3 COM Client Life Cycle COM Object Life Cycle

13 QueryInterface() 特性 n 假設一個 COM Object1 實作三個 COM Interface:I1 I2 I3;pI1 與 pI2 與 pI3 各自為其 指標, 則 QueryInterface() 具下列特性 : – 反射性 :pI1->QueryInterface(IID_I1,ppv); 必定成立 – 對稱性 :pI1->QueryInterface(IID_I2,&pI2); 成立後, 則 pI2->QueryInterface(IID_I1,&pI1); 必定成立 – 遞移性 :pI1->QueryInterface(IID_I2,ppv); 成立, 且 pI2->QueryInterface(IID_I3,ppv); 成立, 則 pI1->QueryInterface(IID_I3,ppv); 必定成立

14 可扮演的 COM 角色 COM Client COM Interface COM Object COM 定 自定 COM 定 自定 COM 定自定 COM 定自定 COM 定 (1)(4)(2)(5)(6) ( 不可能 ) (8) ( 不可能 ) COM 定 :COM Defined 自定 :Custom Defined

15 COM Client 程式 ( 操作 IMalloc) class CTest1View : public CScrollView { private: int m_iLines; int m_iFontHigh; protected: // create from serialization only CTest1View(); DECLARE_DYNCREATE(CTest1View) // Attributes public: CTest1Doc* GetDocument(); CPoint m_Lines; IMalloc *m_pIMalloc; BOOL m_fAllocations; // Operations public: void ShowText(const CString&); BOOL HaveAllocator(void); BOOL DoAllocations(BOOL); BOOL HaveAllocations(void); void FreeAllocations(BOOL); ………

16 CTest1View::CTest1View() { m_Lines=CPoint(0,0); m_pIMalloc=NULL; m_fAllocations=FALSE; } CTest1View::~CTest1View() { FreeAllocations(TRUE); CoUninitialize(); // 停止 COM 服務 } void CTest1View::OnInitialUpdate() { CClientDC dc(this); TEXTMETRIC m; dc.GetTextMetrics(&m); m_iLines=0; m_iFontHigh=m.tmHeight; SetScrollSizes(MM_TEXT,CSize(1000,2000)); CScrollView::OnInitialUpdate(); CoInitialize(NULL); // 啟動 COM 服務 } void CTest1View::OnCogetmalloc() { HRESULT hr; FreeAllocations(TRUE); hr=CoGetMalloc(1,&m_pIMalloc);// 建立 Imalloc bject, 並取得 Interface 指標 if (SUCCEEDED(hr)) ShowText("Allocator OK"); else ShowText("Allocator failed"); }

17 void CTest1View::OnRelease() { if (!HaveAllocator()) { ShowText("Don't have any allocator"); return; } FreeAllocations(TRUE); ShowText("Release complete"); } void CTest1View::FreeAllocations(BOOL fRelease) { int i; CTest1Doc* pDoc=GetDocument(); ASSERT_VALID(pDoc); if (NULL==m_pIMalloc) return; if (m_fAllocations) { for (i=0;im_ap[i]) m_pIMalloc->Free(pDoc->m_ap[i]); pDoc->m_av[i]=10; pDoc->m_ap[i]=NULL; } m_fAllocations=FALSE; } if (fRelease) { m_pIMalloc->Release(); m_pIMalloc=NULL; } 註 : 欲啟動 COM 基本服務, 要在 StdAfx.h 中引入 ole2.h 執行程式 :Malloc.exe

18 自定的 COM Client/Interface/Object 程式 COM Interface: #ifndef __INTERFACE_H #define __INTERFACE_H BOOL CreateObject1(IUnknown **ppUnk);// 建立 COM Object1 並透過 ppUnk 傳回介面指標 ////////////// Common Definition /////////////// typedef LPVOID* PPVOID; #define DelleteInterfaceImp(p) {if (NULL!=p) {delete p;p=NULL;}} #define ReleaseInterface(p) {if (NULL!=p) {p->Release();p=NULL;}} ////////////// Interface Definition ///////////// DECLARE_INTERFACE_(IOne,IUnknown) { //IUnknown members STDMETHOD(QueryInterface) (THIS_ REFIID,PPVOID) PURE; STDMETHOD_(ULONG,AddRef) (THIS) PURE; STDMETHOD_(ULONG,Release) (THIS) PURE; //IOne members STDMETHOD(GetText) (THIS_ LPSTR,int) PURE; }; typedef IOne* PIone; #endif

19 // File: basetyps.h #define STDMETHODIMP HRESULT STDMETHODCALLTYPE #define STDMETHODIMP_(type) type STDMETHODCALLTYPE #define interface struct #define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method #define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method #define PURE = 0 #define THIS_ #define THIS void #define DECLARE_INTERFACE(iface) interface iface #define DECLARE_INTERFACE_(iface, baseiface) interface iface : public baseiface #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ EXTERN_C const GUID name \ = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } COM Client: class CTest1View : public CScrollView { public: IUnknown *m_pIUnknown; ……… } // test1View.cpp : implementation of the CTest1View class #include DEFINE_GUID(IID_IOne,0x12340000,0x43c2,0x11d0, 0xa2,0xa2,0x44,0x45,0x53,0x54,0x0,0x0); CTest1View::CTest1View() {m_pIUnknown=NULL; } CTest1View::~CTest1View() {ReleaseInterface(m_pIUnknown); }

20 void CTest1View::OnObjectcreate() { if (NULL!=m_pIUnknown) { m_pIUnknown->Release(); ShowText("Delete previous interface"); } if (CreateObject1(&m_pIUnknown)) ShowText("COM Object1 created"); else ShowText("COM Object1 creation failed"); } void CTest1View::OnObjectgettext() { if (NULL==m_pIUnknown) { ShowText("There is no object"); return; } HRESULT hr; IOne *pIOne; const int count=80; char temp[count]; hr=m_pIUnknown->QueryInterface(IID_IOne,(PPVOID)&pIOne); if (FAILED(hr)) { ShowText("Failed to get IOne"); return; } hr=pIOne->GetText(temp,count); if (SUCCEEDED(hr)) ShowText(temp); else ShowText("IOne::GetText() failed"); pIOne->Release(); }

21 void CTest1View::OnObjectrelease() { if (NULL==m_pIUnknown) { ShowText("There is no object"); return; } if (0==m_pIUnknown->Release()) { m_pIUnknown=NULL; ShowText("Object released"); } COM Object: //file:Object.h #ifndef __OBJECT1_H #define __OBJECT1_H //Actual object using Interface Implementation way class CObject1:public IOne { private: DWORD m_iRef; public: CObject1(); ~CObject1(); BOOL Init(); //IUnknown members STDMETHODIMP QueryInterface(REFIID,PPVOID); STDMETHODIMP_(DWORD) AddRef(); STDMETHODIMP_(DWORD) Release(); //IOne members STDMETHODIMP GetText(LPSTR,int); }; typedef CObject1* PCObject1; #endif

22 BOOL CreateObject1(IUnknown **ppUnk) { HRESULT hr; CObject1 *pObj; if (NULL==ppUnk) return FALSE; pObj=new CObject1; if (NULL==pObj) return FALSE; if (!pObj->Init()) return FALSE; hr=pObj->QueryInterface(IID_IUnknown,(PPVOID)ppUnk); return SUCCEEDED(hr); } STDMETHODIMP CObject1::QueryInterface(REFIID riid,PPVOID ppv) { *ppv=NULL; if (IID_IUnknown==riid || IID_IOne==riid) *ppv=this; if (NULL==*ppv) return ResultFromScode(E_NOINTERFACE); ((LPUNKNOWN)*ppv)->AddRef(); return NOERROR; } DWORD CObject1::AddRef() { return ++m_iRef; } DWORD CObject1::Release() { if (0!=--m_iRef) return m_iRef; delete this; return 0; } 執行程式 : FirstCOM.exe


Download ppt "COM Client/Interface/Object Architecture and Implement 國立交通大學資訊科學系 分散式系統實驗室 謝欣君."

Similar presentations


Ads by Google