Chinaunix首页 | 论坛 | 博客
  • 博客访问: 453292
  • 博文数量: 96
  • 博客积分: 6045
  • 博客等级: 大校
  • 技术积分: 906
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-03 11:29
文章分类

全部博文(96)

文章存档

2014年(1)

2012年(22)

2011年(23)

2010年(31)

2008年(1)

2007年(18)

分类: C/C++

2011-04-19 16:54:42

  1. #undef INTERFACE
  2. #define INTERFACE ICustomResolver
  3. DECLARE_INTERFACE_(ICustomResolver, Iunknown)
  4. {
  5.   //** IUnknown methods
  6.    STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID *ppvObj) PURE;
  7.    STDMETHOD_(ULONG,AddRef) (THIS) PURE;
  8.    STDMETHOD_(ULONG,Release) (THIS) PURE;

  9.   //** ICustomResolver methods
  10.    STDMETHOD(Reconcile) (THIS_
  11.                         IReplRowChange *pRowChange,
  12.                         DWORD dwFlags,
  13.                         PVOID pvReserved) PURE;
  14.    STDMETHOD(GetHandledStates) (THIS_
  15.                         DWORD *pResolverBm) PURE;
  16. };

COM中使用的几个宏的解释,也许有点帮助  
   
  *   DECLARE_INTERFACE宏用于创建一个不从其它接口继承的接口。  
      DECLARE_INTERFACE_(注意下划线后缀)用于创建一个从其它接口继承而来的接口。  
      DECLARE_INTERFACE_有两个参数:新接口的名字和该接口的超类的名字。  
   
  *   STDMETHOD宏以声明方法的名字作为参数,方法返回一个标准的COM   HRESULT值。  
      STDMETHOD_宏能够说明自己的返回类型。它的两个参数是方法返回值的类型和方法的名字。  
   
  *   PURE宏解释为   “=0”,说明该函数为纯虚函数。
=======================================================================================
当在定义一个函数时,只有函数返回HRESULT 就要使用STDMETHOD。我们的QueryInterface、SetString 和 GetString 函数返回的是HRESULT。AddRef 和Release 不是。后面的两个返回ULONG。这就是我们用STDMETHOD_(以下 滑线结尾)替换它们两个的原因。然后我们把函数名字放入括号中。如果函数不返回HRESULT,我们需要放入它的返回值的类型,然后在这个函数名前加一个 逗号。在函数名后,在 括号中列出函数的参数。THIS 是指向我们对象( 也就是IExample)的一个指针。如果传给函数的仅仅是这个指针,那么你只需简 单的把THIS 放在括号中。AddRef 和Release 函数就是这种情况。但其它函数有额外的参数。所以我们必须用THIS_(以下划线结尾)。然后我 们列出剩余参数。注意在THIS_和剩余参数之间没有逗号。但是每个剩余参数之间有逗号。最后,我们放一个PURE 字和分号
=============================================================================================
1.必须将INTERFACE宏设置为你正在定义的接口的名字。注意在#define新值之前你需要#undef以前的值。
2.必须使用DECLARE_INTERFACE和DECLARE_INTERFACE_宏为借口生成preliminary bookkeeping. 没有基类的接口使用DECLARE_INTERFACE,从其他接口继承而来的接口使用DECLARE_INTERFACE_。在上面的例子 中,ISample2是从ISample继承而来的。注意:在实践中,你不会找到DECLARE_INTERFACE宏,因为如果没有其它的,所有接口都 从IUnknown继承来的。
3.所有基接口中的方法都必须按照其在基接口中的顺序列出;你自己加的方法要在其后列出。
4.必须使用STDMETHOD或者STDMETHOD_宏来定义方法。如果返回值是HRESULT使用STEMTHOD,如果返回值是其他类型则使用STDMETHOD_。
5.如果某个方法没有参数,参数列表必须是(THIS)。否则你必须把THIS_放在参数列表的左括号后面。
6.参数列表后,分号前必须有PURE。
7.在大括号内必须有BEGIN_INTERFACE 和 END_INTERFACE。
 
以下是上述每条规则的理由
1.使用INTERFACE宏的原因是——它的值将被THIS和THIS_使用。
2.DECLARE_InTERFACE*宏的使用保证了为C和C++生成正确的prologue。对于C,会声明一个vtable结构体,对于C++来说编译器会自动不理vtable。另一方面,因为C++有继承机制,所以该宏必须指明基类保证upcasting正常工作。
3.基类方法必须按照原来的顺序列出,(so that the C vtable structure for your derived class mathches the structure for the base class for the extent that they overlap)因此C中继承类的vtable结构体与基类的vtable匹配,其余的可以覆盖(不知是否翻对)。这一条是为了保留COM原则让继承接口还可以继续做基接口。
4.是用STDMETHOD 和STDMETHOD_宏是为了保证为函数原型定义正确的calling converntion(调用习俗??)。对于C该宏创建了一个指向vtable的指针;对于C++该宏创建了一个虚函数。
5.THIS和THIS_宏的使用使得C声明中显式地声明this参数,该参数在C++中是隐含。参数个数的不用要求的版本(THIS, _THIS )也不同,这个主要决定是否要产生一个逗号。
6.PURE保证了C++虚函数是纯虚函数。COM接口的一个固定的属性是:所有的方法都是纯虚函数。
7.BEGIN_INTERFACE和END_INTERFACE宏生成与编译器有关的goo(什么是goo),它是由编译器厂商提供的用来保证生成的接口与COM的vtable布局原则匹配。尽管对goo的需求随着时间慢慢消失,但是不同的编译器由于历史原因还是需要不同的goo。

阅读(2412) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~