宏定义的极致发挥---让你的普通C++类轻松支持IDispatch自动化接口(二)

本文介绍了对上篇博客中C++类支持IDispatch自动化接口的改进,包括使用成员函数提供属性读写、基类映射表的继承、合并多个基类映射、可选参数支持以及DISPID_VALUE特性。示例代码展示了如何通过宏定义实现这些功能,使得C++类能更好地支持自动化接口,同时提供了简单易懂的使用示例。
摘要由CSDN通过智能技术生成

这是上一篇博客《宏定义的极致发挥---让你的普通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
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值