今天的研究课题:COM!!!
初步看了一下《COM技术内幕》,真是看得头晕眼花,如果现在要对COM有什么评价的话,那么感觉就是:光怪陆离,夷非所思!接口,组件,虚拟函数,多重继承,个个知识点扑面而来,完全是与以前程式设计不同的思路,看这本书唯一的办法就是一点一点啃,细嚼慢咽,生怕出半点差错。(个人觉得比看汇编还要复杂,汇编只是烦,而它却是完全思路的不同)
按照书上的例子写了一个简单的COM组件,并且在主函数中用到了它,程序首先是接口的设计,有IX,IY,IZ三个接口,派生自IUnknown,然后在CA类中实现了接口,CA即代表了一个组件。组件中必须设计好QueryInterface函数,该函数是根据相应的接口IID值设置相应接口的指针,并且返回值指明设置有没有成功。
CreateInstance函数是得到一个指向IUnknown类型的指针,客户需用此函数来创建指向类CA所代表的组件并指向其IUnknown接口的指针。
其中还是有好多的知识点弄不懂,跳过去,等看到后面再跳回来看看。
按照书上的例子写了一个简单的COM组件,并且在主函数中用到了它,程序首先是接口的设计,有IX,IY,IZ三个接口,派生自IUnknown,然后在CA类中实现了接口,CA即代表了一个组件。组件中必须设计好QueryInterface函数,该函数是根据相应的接口IID值设置相应接口的指针,并且返回值指明设置有没有成功。
CreateInstance函数是得到一个指向IUnknown类型的指针,客户需用此函数来创建指向类CA所代表的组件并指向其IUnknown接口的指针。
其中还是有好多的知识点弄不懂,跳过去,等看到后面再跳回来看看。
#include <iostream>
#include <unknwn.h>
#include <objbase.h>
using namespace std;
void trace(char *pmsg)
{
cout<<pmsg<<endl;
}
//Interfaces
interface IX:IUnknown
{
virtual void __stdcall Fx()=0;
};
interface IY:IUnknown
{
virtual void __stdcall Fy()=0;
};
interface IZ:IUnknown
{
virtual void __stdcall Fz()=0;
};
//Forward references for GUIDS
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
//Component
class CA:public IX,public IY
{
//IUnknown implementation
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);
virtual ULONG __stdcall AddRef(){return 0;}
virtual ULONG __stdcall Release() {return 0;}
//Interface IX implementation
virtual void __stdcall Fx(){cout<<"Fx"<<endl;}
//Interface IY implementation
virtual void __stdcall Fy(){cout<<"Fy"<<endl;}
};
HRESULT 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;
}
IUnknown* CreateInstance()
{
IUnknown* PI = static_cast<IX*>(new CA);
PI->AddRef();
return PI;
}
//
//IIDS
//
//{32bb8320-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IX=
{0x32bb8320,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};
//{32bb8321-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IY=
{0x32bb8321,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};
//{32bb8322-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IZ=
{0x32bb8322,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};
//
//Client
//
int main()
{
HRESULT hr;
trace("Client: Get and IUnknown pointer");
IUnknown* pIUnknown=CreateInstance();
trace("Client:Get Interface IX.");
IX* pIX=NULL;
hr=pIUnknown->QueryInterface(IID_IX,(void**)&pIX);
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:Succeeded in getting interface IZ");
pIZ->Fz();
}
else
{
trace("Client:Could not get interface IZ.");
}
trace("Client Get Interface 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* pIUnknownFromIY=NULL;
hr=pIY->QueryInterface(IID_IUnknown,(void**)&pIUnknownFromIY);
if(SUCCEEDED(hr))
{
cout<<"Are the IUnknow pointers equal?";
if(pIUnknownFromIY==pIUnknown)
{
cout<<"Yes PIUnknownFromIY==PIUnknown."<<endl;
}
else
{
cout<<"Yes PIUnknownFromIY!=PIUnknown."<<endl;
}
}
delete pIUnknown;
return 0;
}
#include <unknwn.h>
#include <objbase.h>
using namespace std;
void trace(char *pmsg)
{
cout<<pmsg<<endl;
}
//Interfaces
interface IX:IUnknown
{
virtual void __stdcall Fx()=0;
};
interface IY:IUnknown
{
virtual void __stdcall Fy()=0;
};
interface IZ:IUnknown
{
virtual void __stdcall Fz()=0;
};
//Forward references for GUIDS
extern const IID IID_IX;
extern const IID IID_IY;
extern const IID IID_IZ;
//Component
class CA:public IX,public IY
{
//IUnknown implementation
virtual HRESULT __stdcall QueryInterface(const IID& iid,void** ppv);
virtual ULONG __stdcall AddRef(){return 0;}
virtual ULONG __stdcall Release() {return 0;}
//Interface IX implementation
virtual void __stdcall Fx(){cout<<"Fx"<<endl;}
//Interface IY implementation
virtual void __stdcall Fy(){cout<<"Fy"<<endl;}
};
HRESULT 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;
}
IUnknown* CreateInstance()
{
IUnknown* PI = static_cast<IX*>(new CA);
PI->AddRef();
return PI;
}
//
//IIDS
//
//{32bb8320-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IX=
{0x32bb8320,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};
//{32bb8321-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IY=
{0x32bb8321,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};
//{32bb8322-b41b-11cf-a6bb-0080c7b2d682}
static const IID IID_IZ=
{0x32bb8322,0xb41b,0x11cf,
{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};
//
//Client
//
int main()
{
HRESULT hr;
trace("Client: Get and IUnknown pointer");
IUnknown* pIUnknown=CreateInstance();
trace("Client:Get Interface IX.");
IX* pIX=NULL;
hr=pIUnknown->QueryInterface(IID_IX,(void**)&pIX);
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:Succeeded in getting interface IZ");
pIZ->Fz();
}
else
{
trace("Client:Could not get interface IZ.");
}
trace("Client Get Interface 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* pIUnknownFromIY=NULL;
hr=pIY->QueryInterface(IID_IUnknown,(void**)&pIUnknownFromIY);
if(SUCCEEDED(hr))
{
cout<<"Are the IUnknow pointers equal?";
if(pIUnknownFromIY==pIUnknown)
{
cout<<"Yes PIUnknownFromIY==PIUnknown."<<endl;
}
else
{
cout<<"Yes PIUnknownFromIY!=PIUnknown."<<endl;
}
}
delete pIUnknown;
return 0;
}