COM似乎生来就与C++有关,虽然它一再强调COM本身与语言无关,但由于C语言本身对面相对象支持不够好,也就似乎和COM离得比较远,但也不是不能实现。本文用C模拟实现了COM机制,对于一些在如BREW平台上开发的程序员,和想更深入学习C语言的人或许有那么一点微薄的帮助。
What is COM
1.Component Object Modell(组件对象模型)
2.Reference count
3.Virtual-table(VTBL)
4.QueryInterface
实现
一 基本宏定义
//定义用于接口查询的ID
#define ID_SAMPLE_IQueryInterface 0x00000001
#define ID_SAMPLE_ISampleBase 0x00000002
//定义IBase,所有类的基类
#define IBase(iname) void (*AddRef) (iname*); void (*Release) (iname*)
//定义IQueryInterface,从IBase继承
#define IQueryInterface(iname) IBase(iname); int (*QueryInterface)(iname *, int, void **)
二 例一:基本的Addref和Release
1 接口定义
//定义ISampleBase接口
#define ISampleBase(iname) IBase(iname); void (* show)()
typedef struct SampleBase SampleBase;
//定义虚表
typedef struct ISampleBaseVtbl ISampleBaseVtbl;
struct ISampleBaseVtbl {
ISampleBase(SampleBase);
};
//SampleBase结构体,继承自IBase
struct SampleBase {
ISampleBaseVtbl * pvtbl;//虚表指针
int nref;
};
//宏定义,方便使用
#define SampleBaseAddRef(p) (*(ISampleBaseVtbl **)p)->AddRef(p)
#define SampleBaseRelease(p) (*(ISampleBaseVtbl **)p)->Release(p)
#define SampleBaseShow(p) (*(ISampleBaseVtbl **)p)->show()
2 接口实现
void SampleBase_AddRef(SampleBase * me)
{
++me->nref;
printf("SampleBase 引用计数加一(引用计数为:%d)\n", me->nref);
}
void SampleBase_Release(SampleBase * me)
{
--me->nref;
printf("SampleBase 引用计数减一(引用计数为:%d)\n", me->nref);
//如果引用计数归零,则释放内存
if (0 == me->nref) {
printf("引用计数为零,释放内存\n");
free(me);
}
}
void SampleBase_Show()
{
printf("this is SampleBase show\n");
}
void SampleBase_Init(SampleBase ** me)
{
//为实例和虚函数表分配空间
(*me) = (SampleBase * )malloc(sizeof(SampleBase) + sizeof(ISampleBaseVtbl));
//虚函数表指针指向实际虚函数表位置,两种方法都可
(*me)->pvtbl = (ISampleBaseVtbl * )(((char *)(*me)) + sizeof(SampleBase));
//(*me)->pvtbl = (ISampleBaseVtbl * )((*me) + 1);
(*me)->pvtbl->AddRef = SampleBase_AddRef;
(*me)->pvtbl->Release = SampleBase_Release;
(*me)->pvtbl->show = SampleBase_Show;
(*me)->nref = 1;
printf("创建SampleBase 引用计数为1\n");
}
3 使用
void TestSampleBase()
{
SampleBase * p;
printf("--------TestSampleBase---------\n\n");
SampleBase_Init(&p);
SampleBaseAddRef(p);
SampleBaseRelease(p);
SampleBaseShow(p);
SampleBaseRelease(p);
printf("\n================================\n");
}
三 例二:继承和多态的实现
1 接口定义
#define ISampleInherit(iname) ISampleBase(iname); void (* show2)()
typedef struct SampleInherit SampleInherit;
//定义虚表
typedef struct ISampleInheritVtbl ISampleInheritVtbl;
struct ISampleInheritVtbl {
ISampleInherit(SampleInherit);
};
//SampleInherit结构体,继承自ISampleBase
struct SampleInherit {
ISampleInheritVtbl * pvtbl;
int nref;
};
//宏定义,方便使用
#define SampleInheritAddRef(p) (*(ISampleInheritVtbl **)p)->AddRef(p)
#define SampleInheritRelease(p) (*(ISampleInheritVtbl **)p)->Release(p)
#define SampleInheritShow(p) (*(ISampleInheritVtbl **)p)->show()
#define SampleInheritShow2(p) (*(ISampleInheritVtbl **)p)->show2()
2 接口实现
void SampleInherit_AddRef(SampleInherit * me)
{
++me->nref;
printf("SampleInherit 引用计数加一(引用计数为:%d)\n", me->nref);
}
void SampleInherit_Release(SampleInherit * me)
{
--me->nref;
printf("SampleInherit 引用计数减一(引用计数为:%d)\n", me->nref);
if (0 >= me->nref) {
printf("引用计数为零,释放内存\n");
free(me);
}
}
void SampleInherit_Show()
{
printf("this is SampleInherit show\n");
}
void SampleInherit_Show2()
{
printf("this is SampleInherit show2\n");
}
void SampleInherit_Init(SampleInherit ** me)
{
(*me) = (SampleInherit * )malloc(sizeof(SampleInherit) + sizeof(ISampleInheritVtbl));
//(*me)->pvtbl = (ISampleInheritVtbl * )(((char *)(*me)) + sizeof(SampleInherit));
(*me)->pvtbl = (ISampleInheritVtbl * )((*me) + 1);
(*me)->pvtbl->AddRef = SampleInherit_AddRef;
(*me)->pvtbl->Release = SampleInherit_Release;
(*me)->pvtbl->show = SampleInherit_Show;
(*me)->pvtbl->show2 = SampleInherit_Show2;
(*me)->nref = 1;
printf("创建SampleInherit 引用计数为1\n");
}
3 使用
void TestSampleInherit()
{
SampleInherit * p;
printf("-------TestSampleInherit--------\n\n");
SampleInherit_Init(&p);
SampleInheritShow(p);
SampleInheritShow2(p);
SampleBaseShow(p);//以派生类实例调用基类接口,多态关键
SampleInheritRelease(p);
printf("\n================================\n");
}
四 例三:多重继承和接口查询的实现
1 接口定义
#define ISampleInherit3(iname) IQueryInterface(iname); void (* show3)()
typedef struct SampleInherit3 SampleInherit3;
//定义虚表
typedef struct ISampleInherit3Vtbl ISampleInherit3Vtbl;
struct ISampleInherit3Vtbl {
ISampleInherit3(SampleInherit3);
};
typedef struct {
ISampleBaseVtbl * pvt;
SampleInherit3 * pme;
}IISampleBase;
//SampleInherit3结构体,同时继承自IQueryInterface和SampleBase
struct SampleInherit3 {
ISampleInherit3Vtbl * pvtbl;
int nref;
IISampleBase a;
ISampleBaseVtbl vta;
};
//宏定义,方便使用
#define SampleInherit3AddRef(p) (*(ISampleInherit3Vtbl **)p)->AddRef(p)
#define SampleInherit3Release(p) (*(ISampleInherit3Vtbl **)p)->Release(p)
#define SampleInherit3QueryInterface(p,ID,ppo) (*(ISampleInherit3Vtbl **)p)->QueryInterface(p,ID,ppo)
#define SampleInherit3Show3(p) (*(ISampleInherit3Vtbl **)p)->show3()
2 接口实现
void SampleInherit3_AddRef(SampleInherit3 * me)
{
++me->nref;
printf("SampleInherit3 引用计数加一(引用计数为:%d)\n", me->nref);
}
void SampleInherit3_Release(SampleInherit3 * me)
{
--me->nref;
printf("SampleInherit3 引用计数减一(引用计数为:%d)\n", me->nref);
if (0 >= me->nref) {
printf("引用计数为零,释放内存\n");
free(me);
}
}
int SampleInherit3_QueryInterface(SampleInherit3 * me, int iid, void ** ppo)
{
if (ID_SAMPLE_IQueryInterface == iid) {
*ppo = me;
printf("(该实例支持QueryInterface接口)\n");
SampleInherit3_AddRef(me);
return 1;
} else if (ID_SAMPLE_ISampleBase == iid) {
*ppo = &me->a;
printf("(该实例支持SampleBase接口)\n");
SampleInherit3_AddRef(me);
return 1;
} else {
*ppo = 0;
return 0;
}
}
void SB_AddRef(SampleBase * me)
{
SampleInherit3AddRef(((IISampleBase*)me)->pme);
}
void SB_Release(SampleBase * me)
{
SampleInherit3Release(((IISampleBase*)me)->pme);
}
void SampleInherit3_Show()
{
printf("this is SampleInherit3 show\n");
}
void SampleInherit3_Show3()
{
printf("this is SampleInherit3 show3\n");
}
void SampleInherit3_Init(SampleInherit3 ** me)
{
(*me) = (SampleInherit3 * )malloc(sizeof(SampleInherit3) + sizeof(ISampleInherit3Vtbl));
//(*me)->pvtbl = (ISampleInheritVtbl * )(((char *)(*me)) + sizeof(SampleInherit));
(*me)->pvtbl = (ISampleInherit3Vtbl * )((*me) + 1);
(*me)->pvtbl->AddRef = SampleInherit3_AddRef;
(*me)->pvtbl->Release = SampleInherit3_Release;
(*me)->pvtbl->QueryInterface = SampleInherit3_QueryInterface;
(*me)->pvtbl->show3 = SampleInherit3_Show3;
(*me)->nref = 1;
(*me)->vta.AddRef = SB_AddRef;
(*me)->vta.Release = SB_Release;
(*me)->vta.show = SampleInherit3_Show;
(*me)->a.pvt = &(*me)->vta;
(*me)->a.pme = (*me);
printf("创建SampleInherit3 引用计数为1\n");
}
3 使用
void TestSampleInherit3()
{
SampleInherit3 * p;
SampleBase * a;
printf("-------TestSampleInherit3--------\n\n");
SampleInherit3_Init(&p);
SampleInherit3Show3(p);
if (SampleInherit3QueryInterface(p,ID_SAMPLE_ISampleBase,&a)) {
SampleBaseShow(a);
SampleBaseRelease(a);
}
SampleInherit3Release(p);
printf("\n=================================\n");
}
小结
本文通过三个简单的例子,模拟了C++的继承和多态,以及COM机制。具体的实现(如BREW平台)要复杂的多,定义了大量的宏,但基本原理都一样。