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

Posted on 2011-01-13 20:44 一桶浆糊

这是上一篇博客《宏定义的极致发挥---让你的普通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(CComVariant& vDst, VARIANT* pSrc) { return vDst=*pSrc, true; }
};

template<>
class CVarTypeInfoEx<CComVariant> : public CVarTypeInfoEx<VARIANT>
{
public:
	static HRESULT Assign(CComVariant& tDst, VARIANT* pSrc)
	{
		tDst = *pSrc;
		return S_OK;
	}
	static CComVariant Value(CComVariant& v)
	{
		return v;
	}
};

//template<>
//class CVarTypeInfoEx<CComBSTR> : public CVarTypeInfoEx<BSTR>
//{
//public:
//	static HRESULT Assign(CComBSTR& tDst, VARIANT* pSrc)
//	{
//		CComVariant v;
//		if (FAILED(v.ChangeType(VT, pSrc))) return DISP_E_BADVARTYPE;
//		tDst
//#pragma warning(push)
//#pragma warning(disable:4800)
//		tDst = v.*pmField;
//#pragma warning(pop)
//		return S_OK;
//	}
//	static CComBSTR Value(CComVariant& v)
//	{
//		return v.*pmField;
//	}
//};

//////////////////////////////////////////////////////////////////////////
template<>
class CVarTypeInfo< bool >
{
public:
	static const VARTYPE VT = VT_BOOL;
	static VARIANT_BOOL VARIANT::* const pmField;
};

__declspec( selectany ) VARIANT_BOOL VARIANT::* const CVarTypeInfo< bool >::pmField = &VARIANT::boolVal;

// 扩充CComBSTR 类型,用这种类型代替BSTR,能防止内存泄露或者内存释放错误
template<>
class CVarTypeInfo< CComBSTR >
{
public:
	static const VARTYPE VT = VT_BSTR;
	static BSTR VARIANT::* const pmField;
};

__declspec( selectany ) BSTR VARIANT::* const CVarTypeInfo< CComBSTR >::pmField = &VARIANT::bstrVal;

// END of CVarTypeInfo. 使用者可以自行扩充新的类型,例如用CString来保存字符串
//////////////////////////////////////////////////////////////////////////

// 定义多参数的模板类
//////////////////////////////////////////////////////////////////////////
// 可选参数模板类,

#define __optparam(n, ...) typename T##n=int,
#define __optparam_end(n, ...) typename T##n=int
#define __optvalue(n, ...) T##n t##n=0,
#define __optvalue_end(n, ...) T##n t##n=0
#define __optswitch(n, ...) case n: return CComVariant(t##n);

template<int nT=1, __repeat(15, __optparam, __optparam)  __repeat(15, __optvalue, __optvalue_end) >
class _ParamsOpt
{
public:
	static UINT Count() { return nT; }
	static CComVariant DefaultValue(UINT index)
	{
		switch (index)
		{
			__repeat(15, __optswitch, __optswitch)
		}
		return CComVariant();
	}
};

// 0个参数的特化模板
//template<>
class _ParamsOpt_0
{
public:
	static UINT Count() { return 0; }
	static CComVariant DefaultValue(UINT) { return CComVariant(); }
};


// 方法工具模板类和工具宏
#define __tparam(n, ...) typename T##n,
#define __tparam_end(n, ...) typename T##n
#define __param_type(n, ...) if (n<=dp->cArgs && !CVarTypeInfoEx<T##n>::ChangeType(v[n-1], &dp->rgvarg[dp->cArgs-n])) return E_INVALIDARG;
#define __funcparam(n, ...) CVarTypeInfoEx<T##n>::Value(n<=dp->cArgs ? v[n-1] : tOptions::DefaultValue(n-(Count()-tOptions::Count()))),	//.*CVarTypeInfo<T##n>::pmField,
#define __funcparam_end(n, ...) CVarTypeInfoEx<T##n>::Value(n<=dp->cArgs ? v[n-1] : tOptions::DefaultValue(n-(Count()-tOptions::Count())))	//v[n-1].*CVarTypeInfo<T##n>::pmField
#define __funcparam_type(n, ...) T##n,
#define __funcparam_type_end(n, ...) T##n
#define __method_helper_t(n, ...) /
	template<class TT, typename rettype, __repeat(n, __tparam, __tparam) class tOptions/*=_ParamsOpt_N<>*/, rettype (TT::* func)(__repeat(n, __funcparam_type, __funcparam_type_end)) > /
	class _MethodHelper_##n /
	{ /
	public: /
	static UINT Count() { return n; } /
	static HRESULT CallMethod (LPVOID pT, DISPPARAMS* dp, VARIANT* pvarResult) /
	{ /
		if (pT==NULL) return E_FAIL; /
		if (dp->cArgs < n-tOptions::Count()) return DISP_E_BADPARAMCOUNT; /
		CComVariant v[n+1]; /*加是为了避免n==0 时的编译错误*/ /
		__repeat(n, __param_type, __param_type) /
		CComVariant vRet = (reinterpret_cast<TT*>(pT)->*func)( __repeat(n, __funcparam, __funcparam_end) ); /
		if (pvarResult && vRet.vt!=VT_EMPTY) vRet.Detach(pvarResult); /
		return S_OK; /
	} /
	}; /
	/* 返回VOID的特化模板类*/ /
	template<class TT, __repeat(n, __tparam, __tparam) class tOptions/*=OptionalParams<>*/, void (TT::* func)(__repeat(n, __funcparam_type, __funcparam_type_end)) > /
	class _MethodHelper_##n<TT, void, __repeat(n, __funcparam_type, __funcparam_type) tOptions, func> /
	{ /
	public: /
	static UINT Count() { return n; } /
	static HRESULT CallMethod (LPVOID pT, DISPPARAMS* dp, VARIANT* pvarResult) /
	{ /
		if (pT==NULL) return E_FAIL; /
		if (dp->cArgs < n-tOptions::Count()) return DISP_E_BADPARAMCOUNT; /
		CComVariant v[n+1]; /*加是为了避免n==0 时的编译错误*/ /
		__repeat(n, __param_type, __param_type) /
		(reinterpret_cast<TT*>(pT)->*func)( __repeat(n, __funcparam, __funcparam_end) ); /
		return S_OK; /
	} /
	};

// 预定义个方法调用工具模板类
__for_each_number(__method_helper_t)


#define __defparamtype(n,...) int,
#define __defparamtype_end(n,...) int

#define Params(...) __VA_ARGS__,
#define Params0()
//#define ParamsOpt(...)  __VA_ARGS__
#define ParamsOpt1(...)		__VA_ARGS__, _ParamsOpt<1,	__VA_ARGS__, __repeat(14, __defparamtype, __defparamtype_end)
#define ParamsOpt2(...)		__VA_ARGS__, _ParamsOpt<2,	__VA_ARGS__, __repeat(13, __defparamtype, __defparamtype_end)
#define ParamsOpt3(...)		__VA_ARGS__, _ParamsOpt<3,	__VA_ARGS__, __repeat(12, __defparamtype, __defparamtype_end)
#define ParamsOpt4(...)		__VA_ARGS__, _ParamsOpt<4,	__VA_ARGS__, __repeat(11, __defparamtype, __defparamtype_end)
#define ParamsOpt5(...)		__VA_ARGS__, _ParamsOpt<5,	__VA_ARGS__, __repeat(10, __defparamtype, __defparamtype_end)
#define ParamsOpt6(...)		__VA_ARGS__, _ParamsOpt<6,	__VA_ARGS__, __repeat(9, __defparamtype, __defparamtype_end)
#define ParamsOpt7(...)		__VA_ARGS__, _ParamsOpt<7,	__VA_ARGS__, __repeat(8, __defparamtype, __defparamtype_end)
#define ParamsOpt8(...)		__VA_ARGS__, _ParamsOpt<8,	__VA_ARGS__, __repeat(7, __defparamtype, __defparamtype_end)
#define ParamsOpt9(...)		__VA_ARGS__, _ParamsOpt<9,	__VA_ARGS__, __repeat(6, __defparamtype, __defparamtype_end)
#define ParamsOpt10(...)	__VA_ARGS__, _ParamsOpt<10, __VA_ARGS__, __repeat(5, __defparamtype, __defparamtype_end)
#define ParamsOpt11(...)	__VA_ARGS__, _ParamsOpt<11, __VA_ARGS__, __repeat(4, __defparamtype, __defparamtype_end)
#define ParamsOpt12(...)	__VA_ARGS__, _ParamsOpt<12, __VA_ARGS__, __repeat(3, __defparamtype, __defparamtype_end)
#define ParamsOpt13(...)	__VA_ARGS__, _ParamsOpt<13, __VA_ARGS__, __repeat(2, __defparamtype, __defparamtype_end)
#define ParamsOpt14(...)	__VA_ARGS__, _ParamsOpt<14, __VA_ARGS__, __repeat(1, __defparamtype, __defparamtype_end)
#define ParamsOpt15(...)	__VA_ARGS__, _ParamsOpt<15, __VA_ARGS__
#define ParamsOptDefValue(...) __VA_ARGS__

#define _method_helper(T, name, type, paramcnt, ...) _MethodHelper_##paramcnt<T,type,__VA_ARGS__,_ParamsOpt_0,&T::name>::CallMethod
//#define _method_helper_with_option2(T, name, type, paramcnt, opt, ...) _MethodHelper_##paramcnt<T,type,__VA_ARGS__,opt,&T::name>::CallMethod
//#define _method_helper_with_option(T, name, type, paramcnt, params, optparams, optdefvals) _MethodHelper_##paramcnt<T,type,params,optparams,_ParamsOpt<optparams,optdefvals>,&T::name>::CallMethod
#define _method_helper_with_option(T, name, type, paramcnt, params, optparams, optdefvals) _MethodHelper_##paramcnt<T,type,params optparams,optdefvals>,&T::name>::CallMethod

//////////////////////////////////////////////////////////////////////////
// 属性GET工具模板类和工具宏

// 直接访问成员变量时采用这个模板
template<class T, class baseT/*=T*/, typename rettype, rettype baseT::* member>
class _GetHelper
{
public:
	static HRESULT CallGet(LPVOID pT, DISPPARAMS* dp, VARIANT* pvarResult)
	{
		if (pT==NULL) return E_FAIL;
		CComVariant vRet = reinterpret_cast<T*>(pT)->*member;
		if (pvarResult) vRet.Detach(pvarResult);
		return S_OK;
	}
};

// 用户提供了Get函数时采用这个模板,在这种情况下,属性名称不需要跟成员变量名称一致。函数原型是HRESULT GetXXX(VARIANT*)
template<class T, HRESULT (T::* getfunc)(VARIANT*)>
class _GetFuncHelper
{
public:
	static HRESULT CallGet(LPVOID pT, DISPPARAMS* dp, VARIANT* pvarResult)
	{
		if (pT==NULL) return E_FAIL;
		if (pvarResult) return (reinterpret_cast<T*>(pT)->*getfunc)(pvarResult);
		return S_OK;
	}
};

// 对于有默认值的集合类(如colls(1)),必须使用函数方式,因为GET操作也会带参数。函数原型是HRESULT GetXXX(VARIANT index, VARIANT* pResult)
template<class T, HRESULT (T::* getvaluefunc)(VARIANT,VARIANT*)>
class _GetValueFuncHelper
{
public:
	static HRESULT CallGet(LPVOID pT, DISPPARAMS* dp, VARIANT* pvarResult)
	{
		if (pT==NULL) return E_FAIL;
		CComVariant vIndex;
		if (dp->cArgs>0) vIndex = dp->rgvarg[dp->cArgs-1];
		if (pvarResult) return (reinterpret_cast<T*>(pT)->*getvaluefunc)(vIndex, pvarResult);
		return S_OK;
	}
};

#define _get_helper(T, name, type) _GetHelper<T,T,type,&T::name>::CallGet
#define _getfunc_helper(T, name) _GetFuncHelper<T, &T::Get##name>::CallGet
#define _getvalue_helper(T, name) _GetValueFuncHelper<T, &T::Get##name>::CallGet

#define _get_base_helper(T, name, baseT, baseName, type) _GetHelper<T,baseT,type,&baseT::baseName>::CallGet
//#define _getfunc_base_helper(T, name, baseclass) _GetFuncHelper<T, &T::baseclass::Get##name>::CallGet



//////////////////////////////////////////////////////////////////////////
// 属性PUT工具模板类和工具宏

// 直接访问成员变量时采用这个模板
template<class T, class baseT/*=T*/, typename rettype, rettype baseT::* member>
class _PutHelper
{
public:
	static HRESULT CallPut(LPVOID pT, DISPPARAMS* dp, VARIANT* pvarResult)
	{
		if (pT==NULL) return E_FAIL;
		if (dp->cArgs != 1) return DISP_E_BADPARAMCOUNT;
		return CVarTypeInfoEx<rettype>::Assign(reinterpret_cast<T*>(pT)->*member, dp->rgvarg);
//		CComVariant v;
//		if (FAILED(v.ChangeType(CVarTypeInfo<rettype>::VT, dp->rgvarg))) return DISP_E_BADVARTYPE;
//#pragma warning(push)
//#pragma warning(disable:4800)
//		reinterpret_cast<T*>(pT)->*member = v.*CVarTypeInfo<rettype>::pmField;
//#pragma warning(pop)
//		return S_OK;
	}
};

// 用户提供了Set或Put函数时采用这个模板,在这种情况下,属性名称不需要跟成员变量名称一致。函数原型是HRESULT SetXXX(VARIANT*) 或HRESULT PutXXX(VARIANT*)
template<class T, HRESULT (T::* putfunc)(VARIANT*)>
class _PutFuncHelper
{
public:
	static HRESULT CallPut(LPVOID pT, DISPPARAMS* dp, VARIANT* pvarResult)
	{
		if (pT==NULL) return E_FAIL;
		if (dp->cArgs != 1) return DISP_E_BADPARAMCOUNT;
		return (reinterpret_cast<T*>(pT)->*putfunc)(dp->rgvarg);
	}
};

#define _put_helper(T, name, type) _PutHelper<T,T,type,&T::name>::CallPut
#define _putfunc_helper(T, name) _PutFuncHelper<T,&T::Put##name>::CallPut
#define _setfunc_helper(T, name) _PutFuncHelper<T,&T::Set##name>::CallPut

#define _put_base_helper(T, name, baseT, baseName, type) _PutHelper<T,baseT,type,&baseT::baseName>::CallPut
//#define _put_base_helper(T, name, baseT, type) _put_base_map_helper(T,name,baseT,name,type) //_PutHelper<T,baseT,type,&baseT::name>::CallPut


//////////////////////////////////////////////////////////////////////////
// 映射表工具模板类和映射宏
typedef HRESULT (* fnDispMethod)(LPVOID pT, DISPPARAMS* dp, VARIANT* pVarResult);
struct DispMethodData 
{
	LPCOLESTR name;		// property or method name
	DISPID dispid;			// dispid
	fnDispMethod pfnGet;
	fnDispMethod pfnPut;
	fnDispMethod pfnMethod;
};

// {276887CB-4F1A-468d-AF41-D03070C53E68}
EXTERN_C const GUID DECLSPEC_SELECTANY IID_IDispHost = { 0x276887cb, 0x4f1a, 0x468d, { 0xaf, 0x41, 0xd0, 0x30, 0x70, 0xc5, 0x3e, 0x68 } };

MIDL_INTERFACE("276887CB-4F1A-468d-AF41-D03070C53E68")
IDispHost : public IUnknown
{
public:
	virtual LPVOID STDMETHODCALLTYPE GetOwner() = 0;
};

template<class T, bool tManaged=false>
class DispProvider : public IDispatch, public IDispHost
{
private:
	T* _owner;
	ULONG _refcount;

public:
	DispProvider() : _owner(NULL), _refcount(0) {}
	void SetOwner(T* owner) { _owner = owner; }
	// IDispHost
	STDMETHOD_(LPVOID, GetOwner)() { return _owner; }

	/* IDispatch Methods*/
	STDMETHOD_(ULONG, AddRef)() { return tManaged ? ++_refcount : 2; }
	STDMETHOD_(ULONG, Release)()
	{
		if(tManaged && --_refcount==0)
		{
			__if_exists(T::DeleteInstance){T::DeleteInstance(_owner);}
			//delete this;
		};
		return tManaged ? _refcount : 1;
	}
	STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj)
	{
		if (!_owner) return E_UNEXPECTED;
		if (!ppvObj) return E_POINTER;
		*ppvObj = NULL;
		if (IsEqualIID(iid, __uuidof(IUnknown)) ||
			IsEqualIID(iid, __uuidof(IDispatch)))
			*ppvObj = (IDispatch*)this;
		else if (IsEqualIID(iid, IID_IDispHost))
			*ppvObj = (IDispHost*)this;
		if (*ppvObj)
		{
			((LPUNKNOWN)(*ppvObj))->AddRef();
			return S_OK;
		}
		return E_NOINTERFACE;
	}
	STDMETHOD(GetTypeInfoCount)(UINT *pctinfo) { *pctinfo=0; return E_NOTIMPL; }
	STDMETHOD(GetTypeInfo)(UINT /*iTInfo*/, LCID /*lcid*/, ITypeInfo **ppTInfo) { *ppTInfo = NULL; return E_NOTIMPL; }
	STDMETHOD(GetIDsOfNames)(REFIID riid, OLECHAR ** rgszNames, UINT cNames, LCID lcid, DISPID * rgDispId)
	{
		ATLASSERT(cNames == 1);
		if (cNames != 1) return E_NOTIMPL;
		if (!_owner) return E_UNEXPECTED;

		*rgDispId = DISPID_UNKNOWN;
		const DispMethodData* pMap = T::__GetDispMapEntry(*rgszNames);
		if (pMap)
			return *rgDispId = pMap->dispid, S_OK;
		return DISP_E_MEMBERNOTFOUND;
	}
	STDMETHOD(Invoke)(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS * pdispparams, VARIANT *pVarResult, EXCEPINFO * pExcepInfo, UINT * puArgErr)
	{
		if (!_owner) return E_UNEXPECTED;

		LPVOID pVoid = _owner;
		const DispMethodData* pMap = T::__GetDispMapEntry(NULL, &dispIdMember, &pVoid);
		if (pMap)
		{
			//if ((wFlags&DISPATCH_PROPERTYGET) && dispIdMember==DISPID_VALUE && pMap->pfnGet)
			//	return pMap->pfnGet(_owner, pdispparams, pVarResult);

			fnDispMethod pfn = (wFlags&DISPATCH_METHOD) ? pMap->pfnMethod : (wFlags==DISPATCH_PROPERTYGET) ? pMap->pfnGet : pMap->pfnPut;
			if (pfn)
				return pfn(pVoid/*_owner*/, pdispparams, pVarResult);
		}
		return DISP_E_MEMBERNOTFOUND;
	}
};

//////////////////////////////////////////////////////////////////////////
// 映射的类继承工具
#define __parent_map(n, ...) __if_exists(T##n::__GetDispMapEntry) { if (!p) p = T##n::__GetDispMapEntry(pName, pDispid); if (p) pVoid=(LPVOID)static_cast<T##n*>((T*)pVoid); }
#define __tparam16(n,...) typename T##n=int,
#define __tparam16_end(n,...) typename T##n=int

template<class T, __repeat(15, __tparam16, __tparam16_end)>
class _ParentMapHelper
{
public:
	static const DispMethodData* __GetParentsMap(LPCOLESTR pName, DISPID* pDispid, LPVOID* ppVoid)
	{
		LPVOID pVoid = NULL;
		if (ppVoid) pVoid = *ppVoid;
		const DispMethodData* p = NULL;
		__repeat(15, __parent_map, __parent_map)
		if (ppVoid) *ppVoid = pVoid;
		return p;
	}
};

//////////////////////////////////////////////////////////////////////////

// 如果希望合并基类的映射表,...应该列举出基类
#define Begin_Disp_Map(classname, ...) /
private: DispProvider<classname> __disp; /
public: /
	virtual IDispatch* GetDispatch() { return __disp.SetOwner(this), (IDispatch*)&__disp; } /
	static const DispMethodData* __GetDispMapEntry(LPCOLESTR pszByName=NULL/*find by name*/, DISPID* pByDispid=NULL/*find by dispid*/, LPVOID* ppVoid=NULL/*offset of parent*/) /
	{ /
		typedef classname owner_class; /
		typedef _ParentMapHelper<classname, __VA_ARGS__> parent_map_class; /
		static const DispMethodData __map_entry[] = {

#define Begin_Auto_Disp_Map(classname, ...) /
private: DispProvider<classname, true> __disp; classname** __ext_ref; /
private: /*classname();*/ /
public: /
	virtual IDispatch* GetDispatch() { return (IDispatch*)&__disp; } /
	virtual void SetExternalRef(classname** ppref) { __ext_ref=ppref; } /
	static void DeleteInstance(classname* p) { if (p && p->__ext_ref) *p->__ext_ref=NULL; delete p; } /
	static HRESULT CreateInstance(IDispatch** ppDisp, classname** ppOwner=NULL, BOOL bDetach=FALSE) /
	{ /
		if (ppOwner) *ppOwner = NULL; /
		if (ppDisp==NULL) return E_POINTER; /
		*ppDisp = NULL; /
		classname* pOwner = new classname; /
		if (pOwner==NULL) return E_OUTOFMEMORY; /
		pOwner->__ext_ref = NULL; /
		pOwner->__disp.SetOwner(pOwner); /
		if (!bDetach) pOwner->__disp.AddRef(); /
		if (ppOwner) *ppOwner = pOwner; /
		*ppDisp = (IDispatch*)&pOwner->__disp; /
		return S_OK; /
	} /
	static const DispMethodData* __GetDispMapEntry(LPCOLESTR pszByName=NULL/*find by name*/, DISPID* pByDispid=NULL/*find by dispid*/, LPVOID* ppVoid=NULL/*offset of parent*/) /
	{ /
		typedef classname owner_class; /
		typedef _ParentMapHelper<classname, __VA_ARGS__> parent_map_class; /
		static const DispMethodData __map_entry[] = {

#define Disp_PropertyGet(dispid, name, ...) /
			{OLESTR(#name), dispid, /
			__if_exists(owner_class::Get##name){_getfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Get##name){ /
				__if_exists(owner_class::name){_get_helper(owner_class,name,__VA_ARGS__)} /
				__if_not_exists(owner_class::name){NULL /
					__pragma(message("WARNING: property '" #name "' can't be got, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
				} /
			}, /
			NULL, NULL},

#define Disp_PropertyGet_Base_Ex(dispid, name, baseclass, basename, ...) /
			{OLESTR(#name), dispid, /
			__if_exists(owner_class::Get##name){_getfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Get##name){ /
				__if_exists(owner_class::basename){_get_base_helper(owner_class,name,baseclass,basename__VA_ARGS__)} /
				__if_not_exists(owner_class::basename){NULL /
					__pragma(message("WARNING: property '" #name "' can't be got, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
				} /
			}, /
			NULL, NULL},

#define Disp_PropertyGet_Base(dispid, name, baseclass, ...) Disp_PropertyGet_Base_Ex(dispid, name, baseclass, name, __VA_ARGS__)

#define Disp_ValueGet(name, ...) /
			{OLESTR(#name), DISPID_VALUE, /
			__if_exists(owner_class::Get##name){_getvalue_helper(owner_class,name)} /
			__if_not_exists(owner_class::Get##name){ /
				__pragma(message("WARNING: property '" #name "' can't be got, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
			}, /
			NULL, NULL},

#define Disp_PropertyPut(dispid, name, ...) /* ...==type */ /
			{OLESTR(#name), dispid, NULL, /
			__if_exists(owner_class::Set##name){_setfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Set##name){ /
				__if_exists(owner_class::Put##name){_putfunc_helper(owner_class,name)} /
				__if_not_exists(owner_class::Put##name){ /
					__if_exists(owner_class::name){_put_helper(owner_class,name,__VA_ARGS__)} /
					__if_not_exists(owner_class::name){NULL /
						__pragma(message("WARNING: property '" #name "' can't be put, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
					} /
				} /
			}, /
			NULL},

#define Disp_PropertyPut_Base_Ex(dispid, name, baseclass, basename, ...) /* ...==type */ /
			{OLESTR(#name), dispid, NULL, /
			__if_exists(owner_class::Set##name){_setfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Set##name){ /
				__if_exists(owner_class::Put##name){_putfunc_helper(owner_class,name)} /
				__if_not_exists(owner_class::Put##name){ /
					__if_exists(owner_class::basename){_put_base_helper(owner_class,name,baseclass,basename__VA_ARGS__)} /
					__if_not_exists(owner_class::basename){NULL /
						__pragma(message("WARNING: property '" #name "' can't be put, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
					} /
				} /
			}, /
			NULL},

#define Disp_PropertyPut_Base(dispid, name, baseclass, ...) Disp_PropertyPut_Base_Ex(dispid, name, baseclass, name, __VA_ARGS__)

#define Disp_Property(dispid, name, ...) /* ...==type */ /
			{OLESTR(#name), dispid, /
			__if_exists(owner_class::Get##name){_getfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Get##name){ /
				__if_exists(owner_class::name){_get_helper(owner_class,name,__VA_ARGS__)} /
				__if_not_exists(owner_class::name){NULL /
					__pragma(message("WARNING: property '" #name "' can't be got, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
				} /
			}, /
			__if_exists(owner_class::Set##name){_setfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Set##name){ /
				__if_exists(owner_class::Put##name){_putfunc_helper(owner_class,name)} /
				__if_not_exists(owner_class::Put##name){ /
					__if_exists(owner_class::name){_put_helper(owner_class,name,__VA_ARGS__)} /
					__if_not_exists(owner_class::name){NULL /
						__pragma(message("WARNING: property '" #name "' can't be put, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
					} /
				} /
			}, /
			NULL},

#define Disp_Property_Base_Ex(dispid, name, baseclass, basename, ...) /* ...==type */ /
			{OLESTR(#name), dispid, /
			__if_exists(owner_class::Get##name){_getfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Get##name){ /
				__if_exists(owner_class::basename){_get_base_helper(owner_class,name,baseclass,basename,__VA_ARGS__)} /
				__if_not_exists(owner_class::basename){NULL /
					__pragma(message("WARNING: property '" #name "' can't be got, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
				} /
			}, /
			__if_exists(owner_class::Set##name){_setfunc_helper(owner_class,name)} /
			__if_not_exists(owner_class::Set##name){ /
				__if_exists(owner_class::Put##name){_putfunc_helper(owner_class,name)} /
				__if_not_exists(owner_class::Put##name){ /
					__if_exists(owner_class::basename){_put_base_helper(owner_class,name,baseclass,basename,__VA_ARGS__)} /
					__if_not_exists(owner_class::basename){NULL /
						__pragma(message("WARNING: property '" #name "' can't be put, and will be ignored. FILE(" __FILE__ ") LINE(" __to_string(__LINE__) ")")) /
					} /
				} /
			}, /
			NULL},

#define Disp_Property_Base(dispid, name, baseclass, ...) Disp_Property_Base_Ex(dispid, name, baseclass, name, __VA_ARGS__)

#define Disp_Method(dispid, name, type, paramcnt, ...) /
			{OLESTR(#name), dispid, NULL, NULL, _method_helper(owner_class,name,type,paramcnt,__VA_ARGS__)},

#define Disp_Method_With_Option(dispid, name, type, paramcnt, params, opts, defvals) /
			{OLESTR(#name), dispid, NULL, NULL, _method_helper_with_option(owner_class,name,type,paramcnt,params,opts,defvals)},

#define End_Disp_Map() /
			{NULL, DISPID_UNKNOWN, NULL, NULL, NULL} /
		}; /
		if (pszByName==NULL && pByDispid==NULL) return __map_entry; /
		for (int i=0; i<sizeof(__map_entry)/sizeof(__map_entry[0]) - 1; i++) /
		{ /
			if (pByDispid) /
			{ /
				if (__map_entry[i].dispid == *pByDispid) return &__map_entry[i]; /
			} /
			else /*if (pszByName)*/ /
			{ /
				if (lstrcmpiW(__map_entry[i].name, pszByName) == 0) return &__map_entry[i]; /
			} /
		} /
		return parent_map_class::__GetParentsMap(pszByName, pByDispid, ppVoid); /
	}


#pragma warning(pop)

#endif // __MACRO_H__

  

posted on 2014-06-09 17:18  honker  阅读(563)  评论(0编辑  收藏  举报