C++ COM編程之QueryInterface函數(一)。本站提示廣大學習愛好者:(C++ COM編程之QueryInterface函數(一))文章只能為提供參考,不一定能成為您想要的結果。以下是C++ COM編程之QueryInterface函數(一)正文
媒介
組件對外頒布的是接口;一個組件可以完成多個接口,也就是說可以對外頒布多個接口,之前也總結過了,你很少會100%的去完整懂得一個組件的一切接口,就像你去進修編程一樣,你簡直弗成能去成為編程中的全才。那末,既然我們不克不及去完整的懂得一個組件供給的一切接口,那末我們在現實開辟中,若何去斷定一個組件能否供給對應的接口呢?看文檔?是的,是個好主張,在文檔的陸地,找到一個常識點,真的很難,糟蹋時光和精神;其實,組件自己就供給對本身查詢的一個接口,讓客戶去訊問組件,問它能否支撐某個接口,在經由屢次的這類訊問以後,客戶關於組件的熟悉將愈來愈清楚;而我這篇文章和下一篇文章就是對這類訊問機制停止具體的分析和總結。
關於IUnknown
下面說到組件自己供給一個對本身查詢的接口,那末這個接口是甚麼呢?這就是年夜名鼎鼎的IUnknown接口了,IUnknown接口在Windows SDK的unknwn.h中界說,它的界說以下:
interface IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, _COM_Outptr_ void **ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
};
這裡的STDMETHODCALLTYPE表現挪用方法,也就是windows API的__stdcall方法。可以看到,在IUnknown中界說了一個名為QueryInterface的函數。客戶可以挪用QueryInterface來斷定組件能否支撐某個特定的接口,而關於剩下的AddRef和Release兩個接口操作,我會在以後的文章中停止總結。
一切的COM接口都須要繼續IUnknown接口;是以,假如某個客戶具有一個IUnknown接口的指針,它其實不須要曉得它所具有的接口指針究竟是指向甚麼類型的,而只須要曉得此接口可以用來查詢其它接口就好了。
因為一切的COM接口都起首繼續了IUnknown,再依據對之前的文章COM編程——接口的面前 的懂得,我們可以曉得每一個接口的vtbl中的前三個函數都是QueryInterface,AddRef和Release。這就使得一切的COM接口都可以被當做IUnknown接口來處置。假如某個接口的vtbl中的前三個函數不是這三個,那末它將不是一個COM接口。因為一切的接口都是從IUnknown繼續而來的,是以一切的接口都支撐QueryInterface。所以,組件的任何一個接口都可以被客戶用來獲得它所支撐的其他接口。因為一切的接口指針同時也將是IUnknown指針,客戶其實不須要零丁保護一個代表組件的指針,它所關懷的將僅僅是接口的指針。
既然,我們可以只用QueryInterface去訊問組件能否支撐某個接口,然則,這一切都是基於取得了IUnknown接口指針以後,能力停止的操作,那末若何取得一個指向組件的IUnknown接口指針呢?我們可以完成一個CreateInstance函數,它樹立一個組件並前往一個IUnknown指針;關於客戶來講,可以挪用CreateInstance取得IUnknown指針,而不消應用new操作符了。在體系的總結了COM的一切基本常識以後,我再說說體系供給的一個創立組件實例的API函數。
關於QueryInterface
IUnknown中包括一個名為QueryInterface的成員函數,客戶可以經由過程此函數來查詢某個組件能否支撐某個特定的接口。若支撐,QueryInterface將前往一個指向此接口的指針;不然前往值將是一個毛病代碼;然後客戶可以接著查詢其它接口。
從QueryInterface函數的聲明中可以看出,QueryInterface有兩個參數,第一個參數標識客戶所需的接口,這個參數是一個接口標識符(IID)構造,在以後的文章中,我會總結有關IID的常識的;第二個參數用來寄存所要求的接口的地址。QueryInterface前往的是一個HRESULT值,它是一個具有特定構造的32位值,以後我也會停止總結的;關於前往的HRESULT值,在現實開辟中,須要應用SUCCEEDED宏或FAILED宏去停止斷定HRESULT值是表現勝利照樣掉敗。
QueryInterface的簡略完成
總結了QueryInterface的簡略完成,說白了,就是簡略工場形式的完成;下面也說了,就是依據客戶供給的IID接口標識符,然後取得對應的接口的指針,前往對應的接口的指針;假如組件支撐客戶指定的接口,那末應前往S_OK和響應的指針;若不支撐,前往值應是E_NOINTERFACE,並將響應的指針前往值置成NULL。上面經由過程一個簡略的例子來講明QueryInterface的簡略完成:
好比有上述的一個構造;接口IX和IY都繼續自IUnknown接口,組件CA完成了IX和IY接口,那末QueryInterface的完成應當像上面如許:
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;
}
static_cast<IUnknown *>(*ppv)->AddRef();
return S_OK;
}
QueryInterface的簡略應用
當我取得了一個IUnknown指針今後,便可以挪用對應的QueryInterface停止查詢了,以下:
void Fod(IUnknown *pI)
{
IX *pIX = NULL;
// Ask for interface IX
HRESULT hr = pI->QueryInterface(IID_IX, (void **)&pIX);
// Check the return value
if (SUCCEEDED(hr))
{
// Use the interface
pIX->Fx();
}
}
完全的例子
下面說了那末多了,如今供給一個完全的例子,將下面的各類實際常識都在現實代碼中停止了理論,讓列位能更好的懂得QueryInterface。(下載)。
總結
QueryInterface懂得起來比擬簡略,然則,它的實際常識照樣必需要去控制的,實際是一切的基本,沒有實際作為支持,任何現實的操作都不會那末靠得住和可托,所以,這篇文章總結的偏於實際多一些。因為QueryInterface部門的內容比擬多,應用一篇文章沒法總結的齊備,所以,以後我還會持續總結關於QueryInterface的第二部門。