一、前言
COM (Component Object Model) 是 Windows 编程中经常使用的组件化技术,其核心是对象模型。对象模型就是一组对象和调用它们的方法,COM是对其进行的一个规范,以保证它们可以在不同的平台上互操作。
COM中,对象是通过接口来进行交互的,而 QueryInterface是连接不同接口之间的关键。本文就来深入了解 QueryInterface,在 COM 中的作用及实现原理。
二、QueryInterface的作用
在COM中,不同对象需要相互之间通信、交互,因为其不同实现方式、接口不同,所以我们需要为其提供一种机制来查找和请求特定的接口。这就是QueryInterface。
在 COM 中,可以通过IID(interface Identifier)来标识一个接口。每个接口都会有一个对应的 IID,其类型为GUID(Globally Unique Identifier,全局唯一标识符)。而 QueryInterface 就是通过获取IID并向系统查询找到对应的接口。
当一个 COM对象被创建出来时,它同时会创建并实现一个 IUnknown 接口。该接口包括三个方法:AddRef、Release 和 QueryInterface。其中 QueryInterface 是 COM 中最重要的方法:COM 中的所有对象,必须支持QueryInterface方法。
三、QueryInterface的实现原理
当系统接收到一个对象的 QueryInterface 调用时,系统会检查此对象内是否有必要的接口,如果有,则返回此接口;如果没有,就返回参数 Result 的值为 E_NOINTERFACE,以表明没有找到所请求的接口。
以下是一个模板实现方法:
```
STDMETHODIMP CMyObject::QueryInterface(REFIID riid, void **ppv) {
if (IsEqualIID(riid, IID_IUnknown)) { // IUnknown
*ppv = (LPVOID)(IUnknown*)this;
}
else if (IsEqualIID(riid, IID_IMyInterface1)) { // IMyInterface1
*ppv = (LPVOID)(IMyInterface1*)this;
}
else if (IsEqualIID(riid, IID_IMyInterface2)) { // IMyInterface2
*ppv = (LPVOID)(IMyInterface2*)this;
}
else {
*ppv = NULL;
return E_NOINTERFACE;
}
AddRef(); // 计数器 +1
return S_OK;
}
```
上面的模板中,判断接口的方法是通过比较IID是否相等来实现的。一般来说,一个类中会实现多个接口,我们可以通过一个switch语句来进行处理。
四、QueryInterface的应用
以Internet Explorer为例,在IE中,QueryInterface的重要作用在于API的拓展,而API的拓展则给程序扩展了很多功能。
```c++
HRESULT STDMETHODCALLTYPE CMyServiceProvider::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
{
HRESULT hr;
*ppvObject = NULL;
if (IsEqualIID(guidService, SID_SHTMLWindow3)) // HTMLWindow3
{
hr = QueryInterface(riid, ppvObject);
}
else if (IsEqualIID(guidService, SID_STopLevelBrowser)) // TopLevelBrowser
{
if (m_bGetTopLevelBrowser)
{
hr = m_spTopLevelBrowser->QueryInterface(riid, ppvObject);
}
else
{
hr = QueryTopLevelBrowser();
if (hr == S_OK)
{
hr = m_spTopLevelBrowser->QueryInterface(riid, ppvObject);
}
}
}
else
{
hr = QueryServiceProvider(guidService, riid, ppvObject);
}
return hr;
}
```
在这个实现中,我们可以看到,Service的GUID有很多种,而当Service的GUID为SID_SHTMLWindow3和SID_STopLevelBrowser时,则会通过QueryInterface来获取IMyInterface1和IMyInterface2的具体实现,从而使程序扩展了很多功能。
总结
本文介绍了 QueryInterface 在COM中的作用、实现原理和应用,对于深入了解 COM 编程,掌握它的核心思想和实现方法有着重要的意义。对于想要开发 Windows 平台上的应用程序(特别是一些系统工具)的开发人员来说,掌握 COM 编程技术将是有益的。