科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件用C模拟实现COM机制——COMSample

用C模拟实现COM机制——COMSample

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

COM似乎生来就与C++有关,虽然它一再强调COM本身与语言无关,但由于C语言本身对面相对象支持不够好,也就似乎和COM离得比较远,但也不是不能实现。

作者:Creaman 来源:CSDN 2008年3月22日

关键字: C C++ 模拟 COM Linux

  • 评论
  • 分享微博
  • 分享邮件

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平台)要复杂的多,定义了大量的宏,但基本原理都一样。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章