转:宏定义的极致发挥---让你的普通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__

  

你可能感兴趣的:(Dispatch)