所有的com接口都继承IUnknown接口,接口定义在win32SDK UNKNWN.h文件中
interface IUnknown{
virtual HRESULT _stdcall QueryInterface(const&IID iid,void *ppv) = 0;
virtual ULONG _stdcall AddRef()=0;
virtual ULONG _stdcall Release() = 0;
}
由于所有的com接口都继承了IUnknown,每个接口的vtbl(虚拟函数表)中的前三个函数都是
QueryInterface AddRef Release,所有的com接口可以被当成IUnknown接口处理。某个接口的
vtbl中的前三个函数不是这三个,它将不是一个com接口。
IUnknown获取 IUnknown* CreateInstance();
QueryInterface函数,客户可以通过此函数查询某个组件是否支持某个特定的接口。支持则返回
一个指向此接口的指针。否则返回一个错误代码,客户可以接着查询其他接口或将组件卸载。
QueryInterface带有两个参数,此参数是一个接口标识符IID 结构
另外一个是需要请求的接口指针。
QueryInterface函数的实现是根据IID 转换成对应的接口指针
if(iid == IID_IX){
*ppv = static_cast<IX*>(this)
}else if(iid = IID_IY){
*ppv = static_cast<IY*>(this)
}
QueryInterface实现规则
QueryInterface 返回的总是同一个IUnknown指针
若客户曾经获取某个接口,那么总能获取此接口
客户可以再次获取已经拥有的接口
客户可以返回到起始接口
若能够从某个接口获取某特定接口,那么可以从任意接口都将可以获取此接口
组件实例只有一个IUnknown接口,当查询组件实例的IUnknown接口时,不论通过哪个接口,所得到的是同一指针值。
为确定两个接口是否指向同一组件,可以通过两个接口查询IUnknown接口,将返回值进行比较。
#include <iostream>
#include <ObjBase.h>
using namespace std;
void trace(const char* msg){cout<<msg<<endl;}
//从其它人意接口都可以使用QueryInterface 来获取CA所实现的任意接口
interface IX:IUnknown{
virtual void _stdcall Fx()=0;
};
interface IY:IUnknown{
virtual void _stdcall Fy()=0;
};
interface IZ:IUnknown{
virtual void _stdcall Fz()=0;
};
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
class CA:public IX, public IY
{
virtual HRESULT _stdcall QueryInterface(const IID& iid,void ** ppv);
virtual ULONG _stdcall AddRef(){return 0;}
virtual ULONG _stdcall Release(){return 0;}
virtual void _stdcall Fx(){cout <<"Fx"<<endl;}
virtual void _stdcall Fy(){cout<<"Fy"<<endl;}
};
HRESULT _stdcall CA::QueryInterface(const IID& iid,void ** ppv)
{
if (iid == IID_IUnknown)
{
trace("QueryInterface:Return pointer to IUnknown.");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
trace("QueryInterface:Return pointer to IX.");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IY)
{
trace("QueryInterface:Return pointer to IY.");
*ppv = static_cast<IY*>(this);
}
else
{
trace("QueryInterface:Interface not supported");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
IUnknown * CreateInstance()
{
IUnknown*pI = static_cast<IX*>(new CA);
pI->AddRef();
return pI;
}
static const IID IID_IX = {0x32bb8320,0xb41b,0x11cf,0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82};
static const IID IID_IY = {0x32bb8321,0xb41b,0x11cf,0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82};
static const IID IID_IZ = {0x32bb8322,0xb41b,0x11cf,0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82};
int main()
{
HRESULT hr;
trace("Client: Get an IUnknown pointer.");
IUnknown *pIUnknown = CreateInstance();//IUnknown是一个指向子类CA 的基类指针
trace("client: Get interface Ix.");
IX* pIX = NULL;
hr = pIUnknown->QueryInterface(IID_IX,(void**)&pIX);//pIUnknown 是指向子类CA的指针 继承了接口IX IY 所以可以找到 组件IX IY 也就是可以将指针强转成子类指针
if (SUCCEEDED(hr))
{
trace("Client: Succeeded getting IX.");
pIX->Fx();
}
trace("client: get interface IY. ");
IY* pIY = NULL;
hr = pIUnknown->QueryInterface(IID_IY,(void**)&pIY);
if (SUCCEEDED(hr))
{
trace("client: Succeeded getting IY.");
pIY->Fy();
}
trace("client: Ask for an unsupported interface.");
IZ* pIZ = NULL;
hr = pIUnknown->QueryInterface(IID_IZ,(void**)&pIZ);
if (SUCCEEDED(hr))
{
trace("client: Succeede in getting interface IZ.");
pIZ->Fz();
}
else
{
trace("client: Could not get interface IZ.");
}
trace("Client: GetInterface IY from interface IX.");
IY*pIYfromIX = NULL;
hr = pIX->QueryInterface(IID_IY,(void**)&pIYfromIX);
if (SUCCEEDED(hr))
{
trace("Client: Succeeded getting IY.");
pIYfromIX->Fy();
}
trace("client: get interface iunknown from IY.");
IUnknown* pIunknownIY = NULL;
hr = pIY->QueryInterface(IID_IUnknown,(void**)&pIunknownIY);
if (SUCCEEDED(hr))
{
cout<<"Are the IUnknown pointers equeal? ";
if (pIunknownIY == pIUnknown)
{
cout<<"yes PIUnknownFromIy == pIunknown. "<<endl;
}else{
cout<<"No,pIUnknownFromIy != pIunknown."<<endl;
}
}
getchar();
delete pIUnknown;
return 0;
}
interface IUnknown{
virtual HRESULT _stdcall QueryInterface(const&IID iid,void *ppv) = 0;
virtual ULONG _stdcall AddRef()=0;
virtual ULONG _stdcall Release() = 0;
}
由于所有的com接口都继承了IUnknown,每个接口的vtbl(虚拟函数表)中的前三个函数都是
QueryInterface AddRef Release,所有的com接口可以被当成IUnknown接口处理。某个接口的
vtbl中的前三个函数不是这三个,它将不是一个com接口。
IUnknown获取 IUnknown* CreateInstance();
QueryInterface函数,客户可以通过此函数查询某个组件是否支持某个特定的接口。支持则返回
一个指向此接口的指针。否则返回一个错误代码,客户可以接着查询其他接口或将组件卸载。
QueryInterface带有两个参数,此参数是一个接口标识符IID 结构
另外一个是需要请求的接口指针。
QueryInterface函数的实现是根据IID 转换成对应的接口指针
if(iid == IID_IX){
*ppv = static_cast<IX*>(this)
}else if(iid = IID_IY){
*ppv = static_cast<IY*>(this)
}
QueryInterface实现规则
QueryInterface 返回的总是同一个IUnknown指针
若客户曾经获取某个接口,那么总能获取此接口
客户可以再次获取已经拥有的接口
客户可以返回到起始接口
若能够从某个接口获取某特定接口,那么可以从任意接口都将可以获取此接口
组件实例只有一个IUnknown接口,当查询组件实例的IUnknown接口时,不论通过哪个接口,所得到的是同一指针值。
为确定两个接口是否指向同一组件,可以通过两个接口查询IUnknown接口,将返回值进行比较。
#include <iostream>
#include <ObjBase.h>
using namespace std;
void trace(const char* msg){cout<<msg<<endl;}
//从其它人意接口都可以使用QueryInterface 来获取CA所实现的任意接口
interface IX:IUnknown{
virtual void _stdcall Fx()=0;
};
interface IY:IUnknown{
virtual void _stdcall Fy()=0;
};
interface IZ:IUnknown{
virtual void _stdcall Fz()=0;
};
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
class CA:public IX, public IY
{
virtual HRESULT _stdcall QueryInterface(const IID& iid,void ** ppv);
virtual ULONG _stdcall AddRef(){return 0;}
virtual ULONG _stdcall Release(){return 0;}
virtual void _stdcall Fx(){cout <<"Fx"<<endl;}
virtual void _stdcall Fy(){cout<<"Fy"<<endl;}
};
HRESULT _stdcall CA::QueryInterface(const IID& iid,void ** ppv)
{
if (iid == IID_IUnknown)
{
trace("QueryInterface:Return pointer to IUnknown.");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IX)
{
trace("QueryInterface:Return pointer to IX.");
*ppv = static_cast<IX*>(this);
}
else if (iid == IID_IY)
{
trace("QueryInterface:Return pointer to IY.");
*ppv = static_cast<IY*>(this);
}
else
{
trace("QueryInterface:Interface not supported");
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
IUnknown * CreateInstance()
{
IUnknown*pI = static_cast<IX*>(new CA);
pI->AddRef();
return pI;
}
static const IID IID_IX = {0x32bb8320,0xb41b,0x11cf,0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82};
static const IID IID_IY = {0x32bb8321,0xb41b,0x11cf,0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82};
static const IID IID_IZ = {0x32bb8322,0xb41b,0x11cf,0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82};
int main()
{
HRESULT hr;
trace("Client: Get an IUnknown pointer.");
IUnknown *pIUnknown = CreateInstance();//IUnknown是一个指向子类CA 的基类指针
trace("client: Get interface Ix.");
IX* pIX = NULL;
hr = pIUnknown->QueryInterface(IID_IX,(void**)&pIX);//pIUnknown 是指向子类CA的指针 继承了接口IX IY 所以可以找到 组件IX IY 也就是可以将指针强转成子类指针
if (SUCCEEDED(hr))
{
trace("Client: Succeeded getting IX.");
pIX->Fx();
}
trace("client: get interface IY. ");
IY* pIY = NULL;
hr = pIUnknown->QueryInterface(IID_IY,(void**)&pIY);
if (SUCCEEDED(hr))
{
trace("client: Succeeded getting IY.");
pIY->Fy();
}
trace("client: Ask for an unsupported interface.");
IZ* pIZ = NULL;
hr = pIUnknown->QueryInterface(IID_IZ,(void**)&pIZ);
if (SUCCEEDED(hr))
{
trace("client: Succeede in getting interface IZ.");
pIZ->Fz();
}
else
{
trace("client: Could not get interface IZ.");
}
trace("Client: GetInterface IY from interface IX.");
IY*pIYfromIX = NULL;
hr = pIX->QueryInterface(IID_IY,(void**)&pIYfromIX);
if (SUCCEEDED(hr))
{
trace("Client: Succeeded getting IY.");
pIYfromIX->Fy();
}
trace("client: get interface iunknown from IY.");
IUnknown* pIunknownIY = NULL;
hr = pIY->QueryInterface(IID_IUnknown,(void**)&pIunknownIY);
if (SUCCEEDED(hr))
{
cout<<"Are the IUnknown pointers equeal? ";
if (pIunknownIY == pIUnknown)
{
cout<<"yes PIUnknownFromIy == pIunknown. "<<endl;
}else{
cout<<"No,pIUnknownFromIy != pIunknown."<<endl;
}
}
getchar();
delete pIUnknown;
return 0;
}