com學習筆記(2)基本的com介面-QueryInterface的實現

來源:互聯網
上載者:User

QueryInterface   接上篇

一.COM介面的開始IUnknown

com起於介面,又歸於介面.

com之所以是com,是因為其繼承了一個名為IUnknown介面
.

IUnknown介面是一個非常有趣的名字.我們第一次看到這個介面,都會非常好奇,名字的由來開發內部肯定是有故事的,或者他們想不出啥好名字也是有可能的.

下面我們來看一下IUnknown介面定義了哪些成員,這篇只講QueryInterface

interface IUnknown
{
virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) =0;
virtual ULONG __stdcall AddRef() =0 ;
virtual ULONG __stdcall Release() =0 ;
};
二.QueryInterface的實現與使用

1.作用

看命名就可以猜這個方法是用來查詢組件是否支援某個特定介面。若支援澤返回指向此介面的指標。

2.參數

QueryInterface方法有兩個參數,

第一個為介面標識符,簡稱IID,全名(Interface Identifier),現在可以只理解為一個常量

第二個參數即為返回的介面指標

3.使用方法

我們先來看範例程式碼

定義一個繼承自IUnknown介面的IX

interface IX : IUnknown
{
virtual void __stdcall Fx() = 0 ;
} ;

若CA實現了該IX介面,則使用如下

static const IID IID_IX = 
{0x32bb8320, 0xb41b, 0x11cf,
{0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82}} ;

void foo(IUnknown* pI)
{
IX* pIX=NULL;
HRESULT hr=pI->QueryInterface(IID_IX,(void**)&pIX);

if(SUCCEEDED(hr)
{
pIX->Fx();
}
}

3.1 HRESULT

HRESULT是一個查詢結果狀態集合,並非true或false可以表示的,所以用SUCCEEDED方法來判斷查詢結果是否成功,失敗的話,介面指標為NULL.

4.QueryInterface的實現

CA繼承了IX,由於IX繼承了IUnknown介面,所以CA也必須實現IUnknown介面成員,我們重新來看一下QueryInterface方法的參數

virtual
HRESULT __stdcall
QueryInterface(const
IID& iid, void
** ppv) =0;

該方法會根據傳輸不同iid,而返回相對應的介面指標,為了示範,我們再定義一個介面IY,CA實現IX和IY,

如下實現

HRESULT __stdcall CA::QueryInterface(const IID& iid, void** ppv)
{
if (iid == IID_IUnknown)
{
*ppv = static_cast<IX*>(this) ;
}
else if (iid == IID_IX)
{
*ppv = static_cast<IX*>(this) ;
}
else if (iid == IID_IY)
{
*ppv = static_cast<IY*>(this) ;
}
else
{
*ppv = NULL ;
return E_NOINTERFACE;
}
return S_OK ;
}

是不是很簡單?,擷取到以後用static_cast
來轉換類型。IID_IUnknown,S_OK,E_NOINTERFACE等都是內建的狀態代碼

5.簡單建立IUnknown

IUnknown* CreateInstance()
{
IUnknown* pI = static_cast<IX*>(new CA) ;
pI->AddRef() ;
return pI ;
}

6.調用介面

int main()
{
HRESULT hr ;
IUnknown* pIUnknown = CreateInstance() ;

IX* pIX = NULL ;
hr = pIUnknown->QueryInterface(IID_IX, (void**)&pIX) ;
if (SUCCEEDED(hr))
{
pIX->Fx() ; // Use interface IX.
}

IY* pIY = NULL ;
hr = pIUnknown->QueryInterface(IID_IY, (void**)&pIY) ;
if (SUCCEEDED(hr))
{
pIY->Fy() ; // Use interface IY.
}

// Delete the component.
delete pIUnknown ;
return 0 ;
}
三.QueryInterface實現準則

1.QueryInterface返回的總是同一IUnknown指標
,貼圖了

2.若使用者曾擷取過某個介面,那麼它將總能擷取此介面

3.使用者可擷取再次擷取過的介面

4.使用者可以返回到起始介面

3和4都可以理解為介面之間的切換。

5.介面可擷取-
擷取到
介面的介面

通過A介面得到B介面,B介面可以擷取C介面,那麼A介面可以直接擷取C介面.



以上就如數學公式一般,猶如com編程的不變真理.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.