这是上一篇博客《宏定义的极致发挥---让你的普通C++类轻松支持IDispatch自动化接口》所展示的示例代码的改进版,改进之处有:
- 1、如果不想直接提供成员作为属性,可以用成员函数的方式提供属性读写。
2、支持基类映射表,即如果基类也实现了映射表,派生类不用重复填表,自动合并基类表项。唯一的要求就是DISPID不要重复。
3、可以同时合并多个基类映射表。
4、添加可选参数支持,比如某个方法有5个参数,后3个为可选参数(有默认值),那么调用者可以只用2个参数来调用。
5、添加DISPID_VALUE支持,类似于VB中的对象默认属性。
简单的使用示例:
class CAnimal { public: bool Sex; Begin_Disp_Map(CAnimal) Disp_Property(1, Sex, bool) End_Disp_Map() }; class CDog : public CAnimal { public: CString Name; long Height; void Drink(); bool Eat(long lType, long lNum); HRESULT GetName(VARIANT* pvName); HRESULT SetName(VARIANT* pvName); Begin_Disp_Map(CDog, CAnimal) Disp_Property(2, Name) Disp_PropertyGet(3, Height, long) Disp_Method(4, Drink, void, 0) Disp_Method(5, Eat, bool, 2, long, long) End_Disp_Map() };
从示例代码看出跟原始版本有如下不同:
1. 基类CAnimal也有映射表,意思是基类可以独立变成自动化对象。
2. CDog可以继承CAnimal的映射表,只需要把基类名加在起始表项里,Begin_Disp_Map(CDog, CAnimal)。如果不想继承基类映射表,去掉基类类名即可,例如 Begin_Disp_Map(CDog)。如果CDog同时派生自另一个也有映射表的基类,比如CFourLegs,可以这样写 Begin_Disp_Map(CDog, CAnimal, CFourLegs)。这样做的话,CDog 将自动拥有 Sex 属性。
3. Name属性将不再直接处理 Name 成员变量,而是通过GetName/SetName来读取和设置,具体的类型转换将由两个函数完成。
以上并没有列举具有可选参数的方法的填表用法,稍微有点复杂,有时间的话在下一篇介绍。
好了,下面是完整的头文件:
#ifndef __MACRO_H__ #define __MACRO_H__ #pragma once #ifndef __cplusplus #error macro.h requires C++ compilation (use a .cpp suffix) #endif #if (_MSC_VER < 1400) #error macro.h requires Visual C++ 2005 and above. #endif #pragma warning(push) #pragma warning(disable:4800) #ifndef DISPID_EXPANDO_BASE #define DISPID_EXPANDO_BASE 3000000 #define DISPID_EXPANDO_MAX 3999999 #define IsExpandoDispid(dispid) (DISPID_EXPANDO_BASE <= dispid && dispid <= DISPID_EXPANDO_MAX) #endif // DISPID_EXPANDO_BASE // // 基础工具宏定义 #define __for_each_number(v, ...) / v(0, __VA_ARGS__) / v(1, __VA_ARGS__) / v(2, __VA_ARGS__) / v(3, __VA_ARGS__) / v(4, __VA_ARGS__) / v(5, __VA_ARGS__) / v(6, __VA_ARGS__) / v(7, __VA_ARGS__) / v(8, __VA_ARGS__) / v(9, __VA_ARGS__) / v(10, __VA_ARGS__) / v(11, __VA_ARGS__) / v(12, __VA_ARGS__) / v(13, __VA_ARGS__) / v(14, __VA_ARGS__) / v(15, __VA_ARGS__) #define __for_each_number_base1(v, ...) / v(1, __VA_ARGS__) / v(2, __VA_ARGS__) / v(3, __VA_ARGS__) / v(4, __VA_ARGS__) / v(5, __VA_ARGS__) / v(6, __VA_ARGS__) / v(7, __VA_ARGS__) / v(8, __VA_ARGS__) / v(9, __VA_ARGS__) / v(10, __VA_ARGS__) / v(11, __VA_ARGS__) / v(12, __VA_ARGS__) / v(13, __VA_ARGS__) / v(14, __VA_ARGS__) / v(15, __VA_ARGS__) // 数值减的常数 #define __cntdec_0 0 #define __cntdec_1 0 #define __cntdec_2 1 #define __cntdec_3 2 #define __cntdec_4 3 #define __cntdec_5 4 #define __cntdec_6 5 #define __cntdec_7 6 #define __cntdec_8 7 #define __cntdec_9 8 #define __cntdec_10 9 #define __cntdec_11 10 #define __cntdec_12 11 #define __cntdec_13 12 #define __cntdec_14 13 #define __cntdec_15 14 #define __cntdec(n) __cntdec_##n // 连接两个符号 #define __connect2(x, y) x##y #define __connect(x, y) __connect2(x, y) // 把符号变成字符串 #define __to_string2(x) #x #define __to_string(x) __to_string2(x) // 生成不同个数的顺序符号 #define __repeat_0(m, ...) #define __repeat_1(m, ...) __repeat_0(m, __VA_ARGS__) m(1, __VA_ARGS__) #define __repeat_2(m, ...) __repeat_1(m, __VA_ARGS__) m(2, __VA_ARGS__) #define __repeat_3(m, ...) __repeat_2(m, __VA_ARGS__) m(3, __VA_ARGS__) #define __repeat_4(m, ...) __repeat_3(m, __VA_ARGS__) m(4, __VA_ARGS__) #define __repeat_5(m, ...) __repeat_4(m, __VA_ARGS__) m(5, __VA_ARGS__) #define __repeat_6(m, ...) __repeat_5(m, __VA_ARGS__) m(6, __VA_ARGS__) #define __repeat_7(m, ...) __repeat_6(m, __VA_ARGS__) m(7, __VA_ARGS__) #define __repeat_8(m, ...) __repeat_7(m, __VA_ARGS__) m(8, __VA_ARGS__) #define __repeat_9(m, ...) __repeat_8(m, __VA_ARGS__) m(9, __VA_ARGS__) #define __repeat_10(m, ...) __repeat_9(m, __VA_ARGS__) m(10, __VA_ARGS__) #define __repeat_11(m, ...) __repeat_10(m, __VA_ARGS__) m(11, __VA_ARGS__) #define __repeat_12(m, ...) __repeat_11(m, __VA_ARGS__) m(12, __VA_ARGS__) #define __repeat_13(m, ...) __repeat_12(m, __VA_ARGS__) m(13, __VA_ARGS__) #define __repeat_14(m, ...) __repeat_13(m, __VA_ARGS__) m(14, __VA_ARGS__) #define __repeat_15(m, ...) __repeat_14(m, __VA_ARGS__) m(15, __VA_ARGS__) #define __last_repeat_0(m, ...) #define __last_repeat_1(m, ...) m(1, __VA_ARGS__) #define __last_repeat_2(m, ...) m(2, __VA_ARGS__) #define __last_repeat_3(m, ...) m(3, __VA_ARGS__) #define __last_repeat_4(m, ...) m(4, __VA_ARGS__) #define __last_repeat_5(m, ...) m(5, __VA_ARGS__) #define __last_repeat_6(m, ...) m(6, __VA_ARGS__) #define __last_repeat_7(m, ...) m(7, __VA_ARGS__) #define __last_repeat_8(m, ...) m(8, __VA_ARGS__) #define __last_repeat_9(m, ...) m(9, __VA_ARGS__) #define __last_repeat_10(m, ...) m(10, __VA_ARGS__) #define __last_repeat_11(m, ...) m(11, __VA_ARGS__) #define __last_repeat_12(m, ...) m(12, __VA_ARGS__) #define __last_repeat_13(m, ...) m(13, __VA_ARGS__) #define __last_repeat_14(m, ...) m(14, __VA_ARGS__) #define __last_repeat_15(m, ...) m(15, __VA_ARGS__) #define __repeat(n, m_begin, m_end, ...) __connect(__repeat_, __cntdec(n))(m_begin, __VA_ARGS__) __connect(__last_repeat_, n)(m_end, __VA_ARGS__) // 基础工具宏结束 // // // Add IDispatch to class // // 扩充CVarTypeInfo 模板类的定义 //template<> //class CVarTypeInfo< void > //{ //public: // static const VARTYPE VT = VT_EMPTY; // //static char VARIANT::* const pmField; //}; template<typename T> class CVarTypeInfoEx : public CVarTypeInfo<T> { public: static HRESULT Assign(T& tDst, VARIANT* pSrc) { CComVariant v; if (FAILED(v.ChangeType(VT, pSrc))) return DISP_E_BADVARTYPE; #pragma warning(push) #pragma warning(disable:4800) tDst = v.*pmField; #pragma warning(pop) return S_OK; } static T Value(CComVariant& v) { return v.*pmField; } static bool ChangeType(CComVariant& vDst, VARIANT* pSrc) { return SUCCEEDED(vDst.ChangeType(VT, pSrc)); } }; template<> class CVarTypeInfoEx<VARIANT> : public CVarTypeInfo<VARIANT> { public: static HRESULT Assign(VARIANT& tDst, VARIANT* pSrc) { return ::VariantCopy(&tDst, pSrc); } static VARIANT Value(CComVariant& v) { return v; } static bool ChangeType