转:宏定义的极致发挥---让你的普通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__
转:宏定义的极致发挥---让你的普通C++类轻松支持IDispatch自动化接口(二)的更多相关文章
- (转载)内联函数inline和宏定义
(转载)http://blog.csdn.net/chdhust/article/details/8036233 内联函数inline和宏定义 内联函数的优越性: 一:inline定义的类的内联函 ...
- [C++ 2011 STL (VS2012 Update4) 源代码阅读系列(2)]熟悉一些宏定义和模版偏特化或叫模版专门化
[C++ 2011 STL (VS2012 Update4) 源代码阅读系列(2)]熟悉一些宏定义和模版偏特化或叫模版专门化 // point_test.cpp : 知识点练习和测试,用于单步调试,跟 ...
- C/C++中宏定义#pragma once与 #ifndef的区别
为了避免同一个文件被include多次,我们可以通过以下两种方式来进行宏定义: 1. #ifndef方式2. #pragma once方式 在能够支持这两种方式的编译器上,二者并没有太大的区别,但是两 ...
- 深入理解UE4宏定义—— GENERATED_BODY
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/72834164 作者:car ...
- iOS 日常工作之常用宏定义大全
转自:http://www.jianshu.com/p/213b3b96cafe 前言: 在工作中, 很多小伙伴都会在PCH文件定义一些常用的宏,但是又怕写这些简单的宏浪费时间,又有时候忘记怎么定义了 ...
- VC中预处理指令与宏定义详解
刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...
- iOS日常工作之常用宏定义大全
前言: 在工作中, 很多小伙伴都会在PCH文件定义一些常用的宏,但是又怕写这些简单的宏浪费时间,又有时候忘记怎么定义了怎么办?本人在工作中也是如此.所以在这里给大家分享一些常用的宏定义,喜欢的小伙伴可 ...
- 读书笔记 effective c++ Item 2 尽量使用const,枚举(enums),内联(inlines),不要使用宏定义(define)
这个条目叫做,尽量使用编译器而不要使用预处理器更好.#define并没有当作语言本身的一部分. 例如下面的例子: #define ASPECT_RATIO 1.653 符号名称永远不会被编译器看到.它 ...
- C++程序设计基础(4)宏定义和内联
1.知识点 1.1宏定义 (1)不带参数的宏定义 #define ERROR_MESSAGE -100 #define SECONDS_PER_DAY 60*60*60 (2)带参数宏定义,这种形式称 ...
随机推荐
- [LeetCode] 711. Number of Distinct Islands II 不同岛屿的个数之二
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
- [LeetCode] 14. Longest Common Prefix 最长共同前缀
Write a function to find the longest common prefix string amongst an array of strings. If there is n ...
- 2,[VS入门教程] 使用Visual Studio写c语言 入门与技巧精品文~~~~优化篇
本文导航: 关闭界面特效以提高流畅度 解决调试时出现"无法查找或打开PDB文件"的符号问题 注册微软账号并在vs登录 使用Visual Studio Team Services,同 ...
- Windows10 64位部署odoo12开发环境
预装Windows10 64位家庭版电脑一台 2019年7月 安装Python,这里的版本选择上有个坑,不要装最新的Python 3.7.x,原因是odoo12依赖pillow 4.0.0库,而这个4 ...
- C++语言编程规范
前言 这里参考了<高质量C++C 编程指南 林锐>.<google C++编程指南>以及<华为C++语言编程规范>编写了这份C++语言编程规范文档,以合理使用 C+ ...
- LeetCode 485:连续最大1的个数 Max Consecutive Ones(python java)
公众号:爱写bug 给定一个二进制数组, 计算其中最大连续1的个数. Given a binary array, find the maximum number of consecutive 1s i ...
- jquery取消绑定的方法
jquery取消绑定的方法 一般用变量控制 不要用unbind() 相应比较慢 <pre> $('.choseitem').on('click', function () { //如果设置 ...
- 企业微信同步LDAP
1.需求 定期同步企业微信的用户信息到 LDAP 中,当有新用户时,会自动发送LDAP的账号密码给该用户邮箱. 2.环境 python 3.x 需要安装两个模块 pip install ldap3 r ...
- 在linux上安装taiga
# taiga 安装配置 1.简介 本文档介绍了如何部署完整的Taiga服务(每个模块都是Taiga平台的一部分). Taiga平台由三个主要组件组成,每个组件在编译时和运行时都有自己的依赖关系: t ...
- 关于source insight 置顶窗口或者处于前台挡住窗口解决办法
两个办法,分别如下: 1.重启source insight: 2.按两次F11: