VS2012中使用纯C实现COM的小问题
用VS2012新建C++工程都预定义了宏__cplusplus,所以引用到的都是C++的定义。但是要用C实现的话,一般都是也就不是C++的了。比如以下代码:
#undef INTERFACE #define INTERFACE IExample DECLARE_INTERFACE_ (INTERFACE, IUnknown) { STDMETHOD (QueryInterface) (THIS_ REFIID, void **) PURE; STDMETHOD_ (ULONG, AddRef) (THIS) PURE; STDMETHOD_ (ULONG, Release) (THIS) PURE; STDMETHOD (SetString) (THIS_ char *) PURE; STDMETHOD (GetString) (THIS_ char *, DWORD) PURE; };
C版本的宏DECLARE_INTERFACE_和C++版本的宏就不是同一个东西。在C中没有class的概念,所以这里使用了struct,而且在C版本中在宏中已经设置了Vtbl,这是最大的区别。C版本的DECLARE_INTERFACE_:
#define DECLARE_INTERFACE_(iface, baseiface) DECLARE_INTERFACE(iface) #define DECLARE_INTERFACE(iface) typedef interface iface { \ struct iface##Vtbl FAR* lpVtbl; \ } iface; \ typedef struct iface##Vtbl iface##Vtbl; \ struct iface##Vtbl
C++版本的DECLARE_INTERFACE_:
#define DECLARE_INTERFACE_(iface, baseiface) interface DECLSPEC_NOVTABLE iface : public baseiface
但奇怪的是__cplusplus没有undef的情况下,也可以声明IExampleVtbl对象,但就是会有红色的波浪线,提示是未定义的标识符,同时能顺利编译通过。而这点也是困惑我的地方。按道理,如果没有undef __cplusplus的话,cl应该执行的是C++版本中的宏。但是其中有一个重要点是文件是以c结尾。对于cl是否是根据文件后缀来选择编译还是根据其他规则也就不得而知了,因为对cl没有太多了解。至少如果文件是以c为后缀的话,编译器能够选择正确的宏版本来执行代码这点是没错的。
因为在编译器中没有undef __cplusplus,宏的定义是直接定位到对应的C++版本的,而这会干扰到我们正常的代码编写,如果我们忘记了的话。比如这个宏:
REFCLSID
#define REFCLSID const IID &
#define REFCLSID const IID * __MIDL_CONST