Posted on 2011-01-13 20:44 一桶浆糊
这是上一篇博客《宏定义的极致发挥---让你的普通C++类轻松支持IDispatch自动化接口》所展示的示例代码的改进版,改进之处有:
简单的使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 |
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来读取和设置,具体的类型转换将由两个函数完成。
以上并没有列举具有可选参数的方法的填表用法,稍微有点复杂,有时间的话在下一篇介绍。
好了,下面是完整的头文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739 |
#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自动化接口(二),布布扣,bubuko.com
转:宏定义的极致发挥---让你的普通C++类轻松支持IDispatch自动化接口(二)
原文地址:http://www.cnblogs.com/honker/p/3778315.html