程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 自動化基礎概念之“COM組件與接口”

自動化基礎概念之“COM組件與接口”

編輯:關於C++

在前文,我預告了我將開始介紹WINX對自動化(Automation)的支持。首先我打算解釋一下自動化(Automation)相關的概念。

我們會分為3個篇幅介紹:

·COM基礎:COM組件(Component)與接口(Interface)

·變體(Variant)與IDispatch(Dispatch調用)

·自動化(Automation)、OA(Office Automation)、二次開發接口(應用程序開發接口,API)與類型庫(TypeLib)

這是第一篇。

COM組件(Component)直觀理解就是一個類,但這不是嚴謹的定義。原因有二:

有的語言(例如C語言)沒有類,但是它可以實現COM組件。

COM組件(Component)通常是一個類,但是它也可能是用多個類來實現。但是對於組件的客戶而言,它是一個類,還是多個類進行實現,它不知道,也不關心。關於用多個類實現COM組件的詳細內容,您可以了解一下COM組件中的“嵌套類實現COM接口(如MFC喜歡的,ATL則傾向於用多重繼承)”、“聚合(AGGREGATION)”方面的內容。

COM組件(Component)是一種基於二進制對象協議的概念。也可以理解為,這是一個二進制意義上的“類”。一個COM組件,對外暴露的不是一組方法(Method),而是一組接口(Interface)。

接口(Interface)這個概念被廣泛用運,一般意義上說是指“類的規格(契約)”。從COM意義上理解接口(Interface),是一種和目前vtbl機制相容的二進制協議,並且vtbl的前三項與IUnknown接口相容(從繼承角度上來講,可以理解為要求從IUnknown繼承,但只是這樣理解而已)。例如,你可以定義如下接口:

interface IFoo : IUnknown
{
virtual void __stdcall fooA() = 0;
virtual int __stdcall fooB(int arg1, int arg2) = 0;
};

但是你也可以不這樣寫,而是這樣純C風格的:

struct IFooVtbl
{
HRESULT (__stdcall *QueryInterface)(void* pThis, const GUID* iid, void** ppv);
ULONG (__stdcall *AddRef)(void* pThis);
ULONG (__stdcall *Release)(void* pThis);
void (__stdcall *fooA)(void* pThis);
int (__stdcall *fooB)(void* pThis, int arg1, int arg2);
};

struct IFoo
{
struct IFooVtbl* vptr;
};

QueryInterface是COM組件(Component)的核心部分,有了它,才使得組件有了發展升級的可能。我們知道,COM中接口(Interface)有一個GUID(全球唯一標識符)與其對應,理論上說,一旦一個接口被發布,那麼它就不應該被修改,以便舊的客戶可以升級使用到新版本的COM組件。要升級你的組件,你應該這樣:

interface IFoo2 : IFoo
{
virtual HRESULT __stdcall newFoo() = 0;
};

客戶需要用到IFoo2中的功能時,就需要用QueryInterface切換到IFoo2:

IFoo* pFoo;
...
IFoo2* pFoo2;
HRESULT hr = pFoo->QueryInterafce(IID_IFoo2, (void**)&pFoo2);
if (SUCCEEDED(hr))
{
// use pFoo2 ...
pFoo2->Release();
}

而IUnknown中的AddRef、Release,則用於管理COM組件的生命周期。對於它我在《C++內存管理變革》中也聊過,這裡不多解釋。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved