COM学习笔记(一):入门及QueryInterface
来源:互联网 发布:本地直通车软件 编辑:程序博客网 时间:2024/06/03 08:04
#include <objbase.h>定义了 -> #define interface struct
#include <windef.h>定义了 ->#define pascal __stdcall
//*****************************************************************************
//COM雏形之前身
#include <iostream.h>
#include <objbase.h>
trace(const char* pMsg){
cout<<pMsg<<endl;
}
interface IX{
virtual void __stdcall Fx1() = 0;
virtual void __stdcall Fx2() = 0;
};
interface IY{
virtual void __stdcall Fy1() = 0;
virtual void __stdcall Fy2() = 0;
};
class CA : public IX,public IY{
public:
virtual void __stdcall Fx1(){cout<<"CA::Fx1"<<endl;}
virtual void __stdcall Fx2(){cout<<"CA::Fx2"<<endl;}
virtual void __stdcall Fy1(){cout<<"CA::Fy1"<<endl;}
virtual void __stdcall Fy2(){cout<<"CA::Fy2"<<endl;}
};
int main(){
trace("Client: Create an instance of the component.");
CA *pA = new CA;
IX *pIX = pA;
trace("Client:Use the IX interface.");
pIX->Fx1();
pIX->Fx2();
IY *pIY = pA;
trace("Client:Use the IY interface.");
pIY->Fy1();
pIY->Fy2();
race("Client: Delete the component.");
delete pA;
return 0;
}
总结:
一:COM接口在C++中是用纯抽象基类实现的。
二:一个COM组件可以提供多个接口。
三:一个C++类可以使用多继承来实现一个可以提供多个接口的组件。
四:用__stdcall标记的函数将使用标准的调用约定,即 这些函数将在返回到调用者之前将参数从栈中删除。Microsoft平台上COM接口所提供的所有函数使用的军事标准的调用约定。
//*****************************************************************************
定义一个纯抽象基类也就是定义了相应的内存结构。但此内存只是在派生类中实现此抽象基类时才会被分配。当派生类继承一个抽象基类时,它将继承此内存结构。COM接口的内存结构同C++编译器为抽象基类所生成的内存结构是相同的。
所有的COM接口都必须继承一个名为IUnknown的接口。这意味着所有COM接口的前三项都是相同的,其中保存的是IUnknown中三个成员函数的实现的地址。
//*****************************************************************************
Interface IUnknown{
HRESULT __stdcall QueryInterface(const IID& iid,void** ppv) = 0;
virtual ULONG __stdcall AddRef() = 0;
virtual ULONG __stdcall Release() = 0;
};
1) 接口查询:定制QueryInterface,客户调用之(若支持,返回一个指向此接口的指针,否则返回一个错误代码)。
若某个接口的vtbl中的前三个函数不是IUnknown的三个成员函数,它将不是一个COM接口。
2) 获取IUknown指针:IUnknown* CreateInstance();它可以建立一个组件并返回一个IUnknown指针,而不必再使用new操作符。(需要自己定制)
eg:
void foo(IUnknown* pI){
IX* pIX = NULL;
HRESULT hr = pI->QueryInterface(IID_IX,(void**)&pIX);
If(SUCCEEDED(hr)){
pIX->Fx();
}
}
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;
}
//*****************************************************************************
一个完整的例子:
// IUnknown.cpp
#include <iostream.h>
#include <objbase.h>
void trace(const char* msg){cout<<msg<<endl;}
interface IX : IUnknown{
virtual void __stdcall Fx() = 0;
};
interface IY : IUnknown{
virtual void __stdcal 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 IUknown.");
*ppv = static_cast<IX*>(this);
}else if(iid == IID_IX){
trace("QueryInterface: Return pointer toIX.");
*ppv = static_cast<IX*>(this);
}else if(iid == IID_IY){
trace("QueryInterface: Return pointer toIY.");
*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}};
// Client
int main(){
HRESULT hr;
trace("Client:Get an IUnknown pointer.");
IUnknown* pInknown = 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.");
IX* pIY = NULL;
hr = pIUnknown->QueryInterface(IID_IY,(void **)&pIY);
if(SUCCEEDED(hr)){
trace("Client: Succeeded getting IY.");
pIX->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 IUnknown pointers equal?";
if(pIUnknownFromIY == pIUnknwon){
cout<<"Yes,pUnknownFromIY == pIUnknown."<<endl;
}else{
cout<<"No,pIUnknownFromIY != pIUnknown."<<endl;
}
}
delete pIUnknown;
return 0;
}
//*****************************************************************************
QueryInterface的实现规则:
1.QueryInterface返回的总是同一IUnknown指针。
2.若客户曾经获取过某个接口,那么它将总能获取此接口。
3.客户可以再次获取已经拥有的接口。
4.客户可以返回到起始接口。
5.若能够从某个接口获取某特定接口,那么可以从任意接口都将可以获取此接口。
- COM学习笔记(一):入门及QueryInterface
- COM笔记-QueryInterface函数 入门
- COM笔记(QueryInterface接口查询)
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- COM笔记-QueryInterface函数
- 【COM学习】之一、QueryInterface
- C++ COM编程之QueryInterface函数(一)
- COM学习笔记三四《COM技术内幕》--接口和QueryInterface函数
- com学习笔记(2)基本的com接口-QueryInterface的实现
- com学习笔记(2)基本的com接口-QueryInterface的实现
- 我不知道
- 后会无期
- 哈希表(散列表)
- 为什么要写技术博客
- uboot中usb storage启动方法
- COM学习笔记(一):入门及QueryInterface
- ubuntu12.04x64安装jd-gui
- Values of attribute 'level' not equal in different manifest snippets-MFC链接问题
- 黑马程序员——static关键字丶main方法丶继承...
- 如何将shp文件作为底图,做成mpt
- 工作问题总结(二十八)JS调用---网页调用C++程序,可传参
- STL 中make_heap学习
- 使用AIDL实现进程间的通信
- andrioid实时数据采集