把该文中实现的代码整理汇总到一个项目中。目前只是实现到一个中间阶段,重点在说明COM接口的实现原理,还没有包含类厂的部分。以后还需陆续添加类厂等高级功能。
文件组成:
ifoo.h COM接口IFoo,接口ID IID_IFoo 声明文件。
outside.c COM接口实现。这里实现IFoo的是一个结构体COutside.
util.h 一些宏定义、全局函数、变量声明文件。
main.c 笔者为实现项目添加的文件。提供main函数、内存管理函数Alloc,Free的实现(封装C运行库函数malloc和free.)、接口ID定义。
COM接口到底是什么?
COM接口是一个指向虚函数表的指针。通过这个指针可以访问内存中某处的各个功能块,执行预定义的功能,完成用户的任务。这些功能块以函数的形式存在(想不出还有其他形式:))并被调用。它们有一个共同点:都包含一个指针参数,指向这些功能要操作的数据地址。在C++中,这个地址就是对象的首地址,也就是类成员函数中隐含的this指针。在C函数中并没有这种现成的便利,因此代码实现中在接口定义时仍使用了接口指针(HRESULT (__stdcall * QueryInterface) (IFoo * This, const IID * const, void **)),而在接口函数实现时根据结构体布局结构,从这个接口指针推算得到对象实例指针。
typedef struct IFoo
{
struct IFooVtbl * lpVtbl;
} IFoo;
typedef struct IFooVtbl IFooVtbl;
struct IFooVtbl
{
HRESULT (__stdcall * QueryInterface) (IFoo * This, const IID * const, void **) ;
ULONG (__stdcall * AddRef) (IFoo * This) ;
ULONG (__stdcall * Release) (IFoo * This) ;
HRESULT (__stdcall * SetValue) (IFoo * This, int) ;
HRESULT (__stdcall * GetValue) (IFoo * This, int *) ;
};
COM接口的要求:
每一个COM接口(指向的虚函数表)的头三个函数必须是IUnknown接口的函数:QueryInterface,AddRef和Release.在C++中,称为从IUnknown接口继承。
对于调用QueryInterface响应查询IID_IUnknwon得到的接口指针值,同一个对象实现的所有接口必须相同。这是判断两个COM对象是否是同一个对象的标准。
宏定义“#define IUNK_VTABLE_OF(x) ((IUnknownVtbl *)((x)->lpVtbl))”说明