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