mummy  1.0.3
MummyCsharpShadowLayerGenerator.cxx
Go to the documentation of this file.
1 //----------------------------------------------------------------------------
2 //
3 // $Id: MummyCsharpShadowLayerGenerator.cxx 442 2009-04-03 19:47:41Z david.cole $
4 //
5 // $Author: david.cole $
6 // $Date: 2009-04-03 15:47:41 -0400 (Fri, 03 Apr 2009) $
7 // $Revision: 442 $
8 //
9 // Copyright (C) 2006-2007 Kitware, Inc.
10 //
11 //----------------------------------------------------------------------------
12 
14 #include "MummyCsharpGenerator.h"
15 #include "MummyLog.h"
16 #include "MummySettings.h"
17 
18 #include "cableClass.h"
19 #include "cableClassType.h"
20 #include "cableFundamentalType.h"
21 #include "cableFunctionType.h"
22 #include "cableMethod.h"
23 #include "cablePointerType.h"
24 #include "cableType.h"
25 
26 #include "gxsys/ios/sstream"
27 
28 
29 //----------------------------------------------------------------------------
31 {
32  this->CsharpGenerator = 0;
33 }
34 
35 
36 //----------------------------------------------------------------------------
38 {
39 }
40 
41 
42 //----------------------------------------------------------------------------
44 {
45  this->EmitClassForShadowLayer(*GetStream(), GetTargetClass());
46  return false;
47 }
48 
49 
50 //----------------------------------------------------------------------------
52 {
53  return this->CsharpGenerator;
54 }
55 
56 
57 //----------------------------------------------------------------------------
59 {
60  this->CsharpGenerator = generator;
61 }
62 
63 
64 //----------------------------------------------------------------------------
65 const char *MummyCsharpShadowLayerGenerator::GetArgName(cable::FunctionType *ftype, unsigned int i)
66 {
67  return this->GetCsharpGenerator()->GetArgName(ftype, i);
68 }
69 
70 
71 //----------------------------------------------------------------------------
72 gxsys_stl::string GetShadowClassName(const cable::Class *c)
73 {
74  gxsys_stl::string s(c->GetName());
75  s += "Shadow";
76  return s;
77 }
78 
79 
80 //----------------------------------------------------------------------------
81 gxsys_stl::string GetPrimaryDelegateCxxType(const cable::Class *c)
82 {
83  return GetShadowClassName(c) + "_PrimaryType";
84 }
85 
86 
87 //----------------------------------------------------------------------------
88 gxsys_stl::string GetSecondaryDelegateCxxType(const cable::Class *c)
89 {
90  return gxsys_stl::string(c->GetName()) + "*";
91 }
92 
93 
94 //----------------------------------------------------------------------------
95 void MummyCsharpShadowLayerGenerator::EmitClassMethodDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *, const cable::Method *m, const unsigned int, int indent, const char *implClassName)
96 {
97  cable::FunctionType *ft = m->GetFunctionType();
98  unsigned int cArgs = ft->GetNumberOfArguments();
99  unsigned int i = 0;
100  cable::Type *argType = 0;
101  cable::Type *retType = ft->GetReturns();
102 
103  EmitIndent(os, indent);
104 
105  // Context:
106 // Emit(os, "/* ");
107 // Emit(os, m->GetContext()->GetName());
108 // Emit(os, " */ ");
109 
110  // Abstract?
111 // if (m->GetPureVirtual())
112 // {
113 // Emit(os, "/* pure virtual */ ");
114 // }
115 
116  // Definitely virtual:
117  if (m->GetVirtual() && !implClassName)
118  {
119  Emit(os, "virtual ");
120  }
121 
122  // Return type:
123  Emit(os, retType->GetCxxType().GetName().c_str());
124  Emit(os, " ");
125 
126  // Class name colon colon:
127  if (implClassName)
128  {
129  Emit(os, implClassName);
130  Emit(os, "::");
131  }
132 
133  // Method name:
134  Emit(os, m->GetName());
135 
136  // Open args:
137  Emit(os, "(");
138 
139  // The real args:
140  for (i= 0; i<cArgs; ++i)
141  {
142  argType = ft->GetArgument(i);
143 
144  // arg "i":
145  Emit(os, argType->GetCxxType().GetName().c_str());
146  Emit(os, " ");
147  Emit(os, GetArgName(ft, i));
148 
149  if (i<cArgs-1)
150  {
151  Emit(os, ", ");
152  }
153  }
154 
155  // Close args:
156  Emit(os, ")");
157 }
158 
159 
160 //----------------------------------------------------------------------------
161 void MummyCsharpShadowLayerGenerator::EmitClassDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const gxsys_stl::vector<cable::Method*>& wrapped_methods, cable::Method*, cable::Method*, cable::Method*, cable::Method*)
162 {
163  unsigned int i = 0;
164  gxsys_stl::string s(GetShadowClassName(c));
165 
166  if (ClassIsA(c, "vtkObject"))
167  {
168  Emit(os, "\n");
169  Emit(os, "\n");
170  Emit(os, "//----------------------------------------------------------------------------\n");
171  Emit(os, "#include \"vtkDebugLeaks.h\"\n");
172  }
173 
174  Emit(os, "\n");
175  Emit(os, "\n");
176  Emit(os, "//----------------------------------------------------------------------------\n");
177 
178  Emit(os, "#undef ");
179  Emit(os, s.c_str());
180  Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
181  Emit(os, "\n");
182  Emit(os, "#ifdef _MSC_VER\n");
183  Emit(os, "#define ");
184  Emit(os, s.c_str());
185  Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
186  Emit(os, "#endif\n");
187  Emit(os, "\n");
188  Emit(os, "#ifdef ");
189  Emit(os, s.c_str());
190  Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
191  Emit(os, "#include \"windows.h\" // HRESULT, FAILED, E_UNEXPECTED\n");
192  Emit(os, "#define ");
193  Emit(os, s.c_str());
194  Emit(os, "_PrimaryType IDispatch*\n");
195  Emit(os, "#else\n");
196  Emit(os, "#define ");
197  Emit(os, s.c_str());
198  Emit(os, "_PrimaryType void*\n");
199  Emit(os, "#define HRESULT long\n");
200  Emit(os, "#define FAILED(hr) ((HRESULT)(hr) < 0)\n");
201  Emit(os, "#define E_UNEXPECTED ((HRESULT)0x8000FFFFL)\n");
202  Emit(os, "#endif\n");
203 
204 
205  Emit(os, "\n");
206  Emit(os, "\n");
207  Emit(os, "//----------------------------------------------------------------------------\n");
208 
209  Emit(os, "class ");
210  Emit(os, s.c_str());
211  Emit(os, " : public ");
212  Emit(os, c->GetQualifiedName().c_str());
213 
214  // Abstract?
215  //if (c->GetAbstract())
216  // {
217  // Emit(os, " /* abstract */");
218  // }
219 
220  Emit(os, "\n");
221 
222  Emit(os, "{\n");
223  Emit(os, "public:\n");
224 
225  // Shadow class always has factory method and DisconnectShadowDelegates:
226  //
227  // The factory method is "create-and-connect" so that it can be made in
228  // one "over-the-boundary" call from the wrapped layer:
229  //
230  EmitIndent(os);
231  Emit(os, "static ");
232  Emit(os, s.c_str());
233  Emit(os, "* CreateShadow(");
234  Emit(os, GetPrimaryDelegateCxxType(c).c_str());
235  Emit(os, " primary);");
236  Emit(os, "\n");
237 
238  EmitIndent(os);
239  Emit(os, "void DisconnectShadowDelegates();");
240  Emit(os, "\n");
241 
242  Emit(os, "\n");
243 
244  // And overrides of all the virtual wrapped methods (including the Register
245  // and UnRegister methods, if any...)
246  //
247  i = 0;
248  for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
249  mit != wrapped_methods.end(); ++mit)
250  {
251  if ((*mit)->GetVirtual())
252  {
253  EmitClassMethodDeclarationForShadowLayer(os, c, *mit, i+1, 1, false);
254  Emit(os, ";\n");
255  }
256  ++i;
257  }
258 
259 
260  Emit(os, "\n");
261  Emit(os, "protected:\n");
262  EmitIndent(os);
263  Emit(os, s.c_str());
264  Emit(os, "();\n");
265  EmitIndent(os);
266  Emit(os, "virtual ~");
267  Emit(os, s.c_str());
268  Emit(os, "();\n");
269 
270 
271  Emit(os, "\n");
272  Emit(os, "private:\n");
273  EmitIndent(os);
274  Emit(os, GetPrimaryDelegateCxxType(c).c_str());
275  Emit(os, " PrimaryDelegate;");
276  Emit(os, "\n");
277  EmitIndent(os);
278  Emit(os, GetSecondaryDelegateCxxType(c).c_str());
279  Emit(os, " SecondaryDelegate;");
280  Emit(os, "\n");
281 
282  // A bool flag for each virtual override indicating whether the shadow
283  // class is currently calling that method on the primary delegate or not:
284  //
285  i = 0;
286  for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
287  mit != wrapped_methods.end(); ++mit)
288  {
289  if ((*mit)->GetVirtual())
290  {
291  EmitIndent(os);
292  Emit(os, "bool CallingPrimary_");
293  Emit(os, (*mit)->GetName());
294  Emit(os, "_");
295  EmitUint(os, i+1);
296  Emit(os, ";\n");
297  }
298 
299  ++i;
300  }
301 
302  Emit(os, "};\n");
303 }
304 
305 
306 //----------------------------------------------------------------------------
307 // The string returned from these Variant functions should be a valid V_ and
308 // VT_ suffix for use with initializing/accessing a VARIANT variable of the
309 // given type...
310 //
311 // For example, in the use case:
312 // VariantInit(&vargs[0]);
313 // V_VT(&vargs[0]) = VT_I4;
314 // V_I4(&vargs[0]) = (long) callData;
315 // This function will receive a cable type representing the C++ type "long"
316 // and return "I4"...
317 //
318 gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantFundamentalTypeString(const cable::Type *t)
319 {
320  gxsys_stl::string s;
321 
322  if (cable::Type::FundamentalTypeId == t->GetTypeId())
323  {
324  s = cable::FundamentalType::SafeDownCast(t)->GetTypeName();
325 
326  switch (cxx::FundamentalType::SafeDownCast(t->GetCxxType().GetType())->GetId())
327  {
328  case cxx::FundamentalType::UnsignedChar:
329  s = "UI1";
330  break;
331 
332  case cxx::FundamentalType::UnsignedShortInt:
333  s = "UI2";
334  break;
335 
336  case cxx::FundamentalType::UnsignedInt:
337  case cxx::FundamentalType::UnsignedLongInt:
338  s = "UI4";
339  break;
340 
341  case cxx::FundamentalType::UnsignedLongLongInt:
342  s = "UI8";
343  break;
344 
345  case cxx::FundamentalType::SignedChar:
346  case cxx::FundamentalType::Char:
347  s = "I1";
348  break;
349 
350  case cxx::FundamentalType::ShortInt:
351  s = "I2";
352  break;
353 
354  case cxx::FundamentalType::Int:
355  case cxx::FundamentalType::LongInt:
356  s = "I4";
357  break;
358 
359  case cxx::FundamentalType::LongLongInt:
360  s = "I8";
361  break;
362 
363  case cxx::FundamentalType::Bool:
364  s = "BOOL";
365  break;
366 
367  case cxx::FundamentalType::Float:
368  s = "R4";
369  break;
370 
371  case cxx::FundamentalType::Double:
372  s = "R8";
373  break;
374 
375  //case cxx::FundamentalType::Void:
376  //case cxx::FundamentalType::WChar_t:
377  //case cxx::FundamentalType::LongDouble:
378  //case cxx::FundamentalType::ComplexFloat:
379  //case cxx::FundamentalType::ComplexDouble:
380  //case cxx::FundamentalType::ComplexLongDouble:
381  //case cxx::FundamentalType::NumberOfTypes:
382  default:
383  break;
384  }
385  }
386 
387  if (s == "")
388  {
390  << "Unhandled variable type. GetVariantFundamentalTypeString returning the empty string...");
391  }
392 
393  return s;
394 }
395 
396 
397 //----------------------------------------------------------------------------
398 gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantTypeString(const cable::Type *t)
399 {
400  gxsys_stl::string s;
401  cable::Type *nested_type = 0;
402 
403  switch (t->GetTypeId())
404  {
405  case cable::Type::EnumerationTypeId:
406  s = "UI4";
407  break;
408 
409  case cable::Type::FundamentalTypeId:
411  break;
412 
413  case cable::Type::ArrayTypeId:
414  s = "ERROR_ArrayTypeId_not_yet_implemented";
415  LogError(me_InternalError, << s.c_str());
416  break;
417 
418  case cable::Type::ClassTypeId:
419  s = "ERROR_passing_class__";
420  s += cable::ClassType::SafeDownCast(t)->GetClass()->GetName();
421  s += "__by_value_not_allowed";
422  LogError(me_InternalError, << s.c_str());
423  break;
424 
425  case cable::Type::PointerTypeId:
426  nested_type = cable::PointerType::SafeDownCast(t)->GetTarget();
427 
428  // IntPtr maps to I4 on 32-bit windows and I8 on 64-bit windows...
429  //
430  if (IsObject(nested_type))
431  {
432  s = "I4";
433  }
434  else if (IsChar(nested_type))
435  {
436  s = "I4";
437  }
438  else if (IsVoid(nested_type))
439  {
440  s = "I4";
441  }
442  else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId())
443  {
444  s = "I4";
445  }
446  else if (cable::Type::PointerTypeId == nested_type->GetTypeId())
447  {
448  s = "I4 /* pointer */";
449  }
450  else
451  {
452  s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type";
453  LogError(me_InternalError, << s.c_str());
454  }
455  break;
456 
457  case cable::Type::ReferenceTypeId:
458  s = "ERROR_ReferenceTypeId_not_yet_implemented";
459  LogError(me_InternalError, << s.c_str());
460  break;
461 
462  case cable::Type::OffsetTypeId:
463  case cable::Type::MethodTypeId:
464  case cable::Type::FunctionTypeId:
465  default:
466  s = "ERROR_No_Variant_type_for_cable_Type_TypeId";
467  LogError(me_InternalError, << s.c_str());
468  break;
469  }
470 
471  if (s == "")
472  {
474  << "Unhandled variable type. GetVariantTypeString returning the empty string...");
475  }
476 
477  return s;
478 }
479 
480 
481 //----------------------------------------------------------------------------
482 gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantTypeCastingString(const cable::Type *t)
483 {
484  gxsys_stl::string s;
485  cable::Type *nested_type = 0;
486 
487  switch (t->GetTypeId())
488  {
489  case cable::Type::EnumerationTypeId:
490  s = "(unsigned int) ";
491  break;
492 
493  case cable::Type::FundamentalTypeId:
494  // No cast needed...
495  s = "";
496  break;
497 
498  case cable::Type::ArrayTypeId:
499  s = "ERROR_ArrayTypeId_not_yet_implemented";
500  LogError(me_InternalError, << s.c_str());
501  break;
502 
503  case cable::Type::ClassTypeId:
504  s = "ERROR_passing_class__";
505  s += cable::ClassType::SafeDownCast(t)->GetClass()->GetName();
506  s += "__by_value_not_allowed";
507  LogError(me_InternalError, << s.c_str());
508  break;
509 
510  case cable::Type::PointerTypeId:
511  nested_type = cable::PointerType::SafeDownCast(t)->GetTarget();
512 
513  // IntPtr maps to I4 on 32-bit windows and I8 on 64-bit windows...
514  //
515  if (IsObject(nested_type))
516  {
517  s = "(int) ";
518  }
519  else if (IsChar(nested_type))
520  {
521  s = "(int) ";
522  }
523  else if (IsVoid(nested_type))
524  {
525  s = "(int) ";
526  }
527  else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId())
528  {
529  s = "(int) ";
530  }
531  else if (cable::Type::PointerTypeId == nested_type->GetTypeId())
532  {
533  s = "(int) /* pointer */";
534  }
535  else
536  {
537  s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type";
538  LogError(me_InternalError, << s.c_str());
539  }
540  break;
541 
542  case cable::Type::ReferenceTypeId:
543  s = "ERROR_ReferenceTypeId_not_yet_implemented";
544  LogError(me_InternalError, << s.c_str());
545  break;
546 
547  case cable::Type::OffsetTypeId:
548  case cable::Type::MethodTypeId:
549  case cable::Type::FunctionTypeId:
550  default:
551  s = "ERROR_No_Variant_type_for_cable_Type_TypeId";
552  LogError(me_InternalError, << s.c_str());
553  break;
554  }
555 
556  return s;
557 }
558 
559 
560 //----------------------------------------------------------------------------
561 void MummyCsharpShadowLayerGenerator::EmitClassImplementationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const gxsys_stl::vector<cable::Method*>& wrapped_methods, cable::Method* factoryM, cable::Method* disposalM, cable::Method* registerM, cable::Method* unRegisterM)
562 {
563  unsigned int i = 0;
564  gxsys_stl::string s(GetShadowClassName(c));
565  gxsys_ios::ostringstream oss;
566  gxsys_stl::string vargs;
567 
568  // Shadow class always has factory method and DisconnectShadowDelegates:
569  //
570  Emit(os, "\n");
571  Emit(os, "\n");
572  Emit(os, "//----------------------------------------------------------------------------\n");
573  Emit(os, "/* static */\n");
574  Emit(os, s.c_str());
575  Emit(os, "* ");
576  Emit(os, s.c_str());
577  Emit(os, "::");
578  Emit(os, "CreateShadow(");
579  Emit(os, GetPrimaryDelegateCxxType(c).c_str());
580  Emit(os, " primary)");
581  Emit(os, "\n");
582  Emit(os, "{\n");
583 
584  EmitIndent(os);
585  Emit(os, s.c_str());
586  Emit(os, "* rv = new ");
587  Emit(os, s.c_str());
588  Emit(os, ";\n");
589 
590  EmitIndent(os);
591  Emit(os, "rv->PrimaryDelegate = primary;\n");
592 
593  EmitIndent(os);
594  Emit(os, "rv->SecondaryDelegate = ");
595  if (factoryM)
596  {
597  Emit(os, c->GetName());
598  Emit(os, "::");
599  Emit(os, factoryM->GetName());
600  Emit(os, "()");
601  }
602  else
603  {
604  Emit(os, "0");
605  }
606  Emit(os, ";\n");
607  Emit(os, "\n");
608 
609  EmitIndent(os);
610  Emit(os, "if (rv->PrimaryDelegate)\n");
611  EmitIndent(os, 2);
612  Emit(os, "{\n");
613  Emit(os, "#ifdef ");
614  Emit(os, s.c_str());
615  Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
616  EmitIndent(os, 2);
617  Emit(os, "rv->PrimaryDelegate->AddRef();\n");
618  Emit(os, "#else\n");
619  Emit(os, "#endif\n");
620  EmitIndent(os, 2);
621  Emit(os, "}\n");
622  Emit(os, "\n");
623 
624  EmitIndent(os);
625  Emit(os, "return rv;\n");
626 
627  Emit(os, "}\n");
628 
629  Emit(os, "\n");
630  Emit(os, "\n");
631  Emit(os, "//----------------------------------------------------------------------------\n");
632  Emit(os, "void ");
633  Emit(os, s.c_str());
634  Emit(os, "::");
635  Emit(os, "DisconnectShadowDelegates()");
636  Emit(os, "\n");
637  Emit(os, "{\n");
638 
639  EmitIndent(os);
640  Emit(os, "if (this->PrimaryDelegate)\n");
641  EmitIndent(os, 2);
642  Emit(os, "{\n");
643  Emit(os, "#ifdef ");
644  Emit(os, s.c_str());
645  Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
646  EmitIndent(os, 2);
647  Emit(os, "this->PrimaryDelegate->Release();\n");
648  Emit(os, "#else\n");
649  Emit(os, "#endif\n");
650  EmitIndent(os, 2);
651  Emit(os, "}\n");
652  EmitIndent(os);
653  Emit(os, "this->PrimaryDelegate = 0;\n");
654  Emit(os, "\n");
655 
656  if (disposalM)
657  {
658  EmitIndent(os);
659  Emit(os, "if (this->SecondaryDelegate)\n");
660  EmitIndent(os, 2);
661  Emit(os, "{\n");
662  EmitIndent(os, 2);
663  Emit(os, "this->SecondaryDelegate->");
664  Emit(os, disposalM->GetName());
665  Emit(os, "();\n");
666  EmitIndent(os, 2);
667  Emit(os, "}\n");
668  }
669 
670  EmitIndent(os);
671  Emit(os, "this->SecondaryDelegate = 0;\n");
672 
673  Emit(os, "\n");
674  Emit(os, "}\n");
675 
676  // And overrides of all the virtual wrapped methods:
677  //
678  i = 0;
679 
680  for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
681  mit != wrapped_methods.end(); ++mit)
682  {
683  if ((*mit)->GetVirtual())
684  {
685  unsigned int argi = 0;
686  unsigned int cArgs = (*mit)->GetFunctionType()->GetNumberOfArguments();
687  cable::Type *retType = (*mit)->GetFunctionType()->GetReturns();
688  bool voidReturn = false;
689  if (IsVoid(retType))
690  {
691  voidReturn = true;
692  }
693 
694  Emit(os, "\n");
695  Emit(os, "\n");
696  Emit(os, "//----------------------------------------------------------------------------\n");
697  EmitClassMethodDeclarationForShadowLayer(os, c, *mit, i+1, 0, s.c_str());
698  Emit(os, "\n");
699  Emit(os, "{\n");
700 
701  if (!voidReturn)
702  {
703  EmitIndent(os);
704  Emit(os, retType->GetCxxType().GetName().c_str());
705  Emit(os, " rv = ");
706  if (cable::Type::PointerTypeId == retType->GetTypeId())
707  {
708  Emit(os, "0");
709  }
710  else if (cable::Type::FundamentalTypeId == retType->GetTypeId())
711  {
712  Emit(os, "(");
713  Emit(os, retType->GetCxxType().GetName().c_str());
714  Emit(os, ") 0");
715  }
716  else
717  {
718  Emit(os, retType->GetCxxType().GetName().c_str());
719  Emit(os, "()");
720  }
721  Emit(os, ";\n");
722  }
723 
724  EmitIndent(os);
725  Emit(os, "HRESULT msl_hr = E_UNEXPECTED;\n");
726  Emit(os, "\n");
727 
728  EmitIndent(os);
729  Emit(os, "if (this->PrimaryDelegate && !this->CallingPrimary_");
730  Emit(os, (*mit)->GetName());
731  Emit(os, "_");
732  EmitUint(os, i+1);
733  Emit(os, ")\n");
734 
735  EmitIndent(os, 2);
736  Emit(os, "{\n");
737 
738  EmitIndent(os, 2);
739  Emit(os, "this->CallingPrimary_");
740  Emit(os, (*mit)->GetName());
741  Emit(os, "_");
742  EmitUint(os, i+1);
743  Emit(os, " = true;\n");
744  Emit(os, "\n");
745 
746  Emit(os, "#ifdef ");
747  Emit(os, s.c_str());
748  Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
749  EmitIndent(os, 2);
750  Emit(os, "IDispatch *msl_pDisp = (IDispatch *) this->PrimaryDelegate;\n");
751  EmitIndent(os, 2);
752  Emit(os, "msl_pDisp->AddRef();\n");
753  Emit(os, "\n");
754  EmitIndent(os, 2);
755  Emit(os, "DISPID msl_dispid = (DISPID) -1;\n");
756 
757  EmitIndent(os, 2);
758  Emit(os, "OLECHAR *msl_name = L\"");
759  Emit(os, (*mit)->GetName());
760  Emit(os, "\";\n");
761 
762  if (cArgs!=0)
763  {
764  EmitIndent(os, 2);
765  Emit(os, "VARIANTARG msl_vargs[");
766  oss.rdbuf()->str("");
767  oss << cArgs << gxsys_ios::ends;
768  vargs = oss.str();
769  Emit(os, vargs.c_str());
770  Emit(os, "];\n");
771  }
772 
773  EmitIndent(os, 2);
774  Emit(os, "DISPPARAMS msl_params;\n");
775  EmitIndent(os, 2);
776  Emit(os, "VARIANT msl_result;\n");
777  EmitIndent(os, 2);
778  Emit(os, "EXCEPINFO msl_excep;\n");
779  EmitIndent(os, 2);
780  Emit(os, "UINT msl_arg = (UINT) -1;\n");
781  Emit(os, "\n");
782  EmitIndent(os, 2);
783  Emit(os, "msl_hr = msl_pDisp->GetIDsOfNames(\n");
784  EmitIndent(os, 3);
785  Emit(os, "IID_NULL,\n");
786  EmitIndent(os, 3);
787  Emit(os, "&msl_name,\n");
788  EmitIndent(os, 3);
789  Emit(os, "1,\n");
790  EmitIndent(os, 3);
791  Emit(os, "LOCALE_USER_DEFAULT,\n");
792  EmitIndent(os, 3);
793  Emit(os, "&msl_dispid);\n");
794  Emit(os, "\n");
795 
796  EmitIndent(os, 2);
797  Emit(os, "if (SUCCEEDED(msl_hr))\n");
798  EmitIndent(os, 3);
799  Emit(os, "{\n");
800 
801  for (argi= 0; argi<cArgs; ++argi)
802  {
803  oss.rdbuf()->str("");
804  oss << "&msl_vargs[" << (cArgs-1-argi) << "]" << gxsys_ios::ends;
805  vargs = oss.str();
806 
807  EmitIndent(os, 3);
808  Emit(os, "VariantInit(");
809  Emit(os, vargs.c_str());
810  Emit(os, ");\n");
811 
812  EmitIndent(os, 3);
813  Emit(os, "V_VT(");
814  Emit(os, vargs.c_str());
815  Emit(os, ") = VT_");
816  Emit(os, GetVariantTypeString((*mit)->GetFunctionType()->GetArgument(argi)).c_str());
817  Emit(os, ";\n");
818 
819  EmitIndent(os, 3);
820  Emit(os, "V_");
821  Emit(os, GetVariantTypeString((*mit)->GetFunctionType()->GetArgument(argi)).c_str());
822  Emit(os, "(");
823  Emit(os, vargs.c_str());
824  Emit(os, ") = ");
825  Emit(os, GetVariantTypeCastingString((*mit)->GetFunctionType()->GetArgument(argi)).c_str());
826  Emit(os, GetArgName((*mit)->GetFunctionType(), argi));
827  Emit(os, ";\n");
828 
829  Emit(os, "\n");
830  }
831 
832  EmitIndent(os, 3);
833  Emit(os, "msl_params.rgvarg = ");
834  if (0 == cArgs)
835  {
836  Emit(os, "0");
837  }
838  else
839  {
840  Emit(os, "&msl_vargs[0]");
841  }
842  Emit(os, ";\n");
843  EmitIndent(os, 3);
844  Emit(os, "msl_params.rgdispidNamedArgs = 0;\n");
845  EmitIndent(os, 3);
846  Emit(os, "msl_params.cArgs = ");
847  if (0 == cArgs)
848  {
849  Emit(os, "0");
850  }
851  else
852  {
853  Emit(os, "sizeof(msl_vargs)/sizeof(msl_vargs[0])");
854  }
855  Emit(os, ";\n");
856  EmitIndent(os, 3);
857  Emit(os, "msl_params.cNamedArgs = 0;\n");
858  Emit(os, "\n");
859  EmitIndent(os, 3);
860  Emit(os, "VariantInit(&msl_result);\n");
861  Emit(os, "\n");
862  EmitIndent(os, 3);
863  Emit(os, "memset(&msl_excep, 0, sizeof(msl_excep));\n");
864  Emit(os, "\n");
865  EmitIndent(os, 3);
866  Emit(os, "msl_hr = msl_pDisp->Invoke(msl_dispid, IID_NULL, LOCALE_USER_DEFAULT,\n");
867  EmitIndent(os, 4);
868  Emit(os, "DISPATCH_METHOD, &msl_params, &msl_result, &msl_excep, &msl_arg);\n");
869  Emit(os, "\n");
870 
871  if (!voidReturn)
872  {
873  EmitIndent(os, 3);
874  Emit(os, "if (SUCCEEDED(msl_hr))\n");
875  EmitIndent(os, 4);
876  Emit(os, "{\n");
877  EmitIndent(os, 4);
878  Emit(os, "rv = (");
879  Emit(os, retType->GetCxxType().GetName().c_str());
880  Emit(os, ") V_");
881  Emit(os, GetVariantTypeString(retType).c_str());
882  Emit(os, "(&msl_result);\n");
883  EmitIndent(os, 4);
884  Emit(os, "}\n");
885  Emit(os, "\n");
886  }
887 
888  EmitIndent(os, 3);
889  Emit(os, "VariantClear(&msl_result);\n");
890 
891  for (argi= 0; argi<cArgs; ++argi)
892  {
893  oss.rdbuf()->str("");
894  oss << "&msl_vargs[" << argi << "]" << gxsys_ios::ends;
895  vargs = oss.str();
896 
897  EmitIndent(os, 3);
898  Emit(os, "VariantClear(");
899  Emit(os, vargs.c_str());
900  Emit(os, ");\n");
901  }
902 
903  EmitIndent(os, 3);
904  Emit(os, "}\n");
905  Emit(os, "\n");
906 
907  EmitIndent(os, 2);
908  Emit(os, "msl_pDisp->Release();\n");
909  Emit(os, "#else\n");
910  Emit(os, "#endif\n");
911  Emit(os, "\n");
912 
913  EmitIndent(os, 2);
914  Emit(os, "this->CallingPrimary_");
915  Emit(os, (*mit)->GetName());
916  Emit(os, "_");
917  EmitUint(os, i+1);
918  Emit(os, " = false;\n");
919 
920  EmitIndent(os, 2);
921  Emit(os, "}\n");
922  Emit(os, "\n");
923 
924 
925  EmitIndent(os);
926  Emit(os, "if (FAILED(msl_hr) || this->CallingPrimary_");
927  Emit(os, (*mit)->GetName());
928  Emit(os, "_");
929  EmitUint(os, i+1);
930  Emit(os, ")\n");
931 
932  EmitIndent(os, 2);
933  Emit(os, "{\n");
934 
935  // Do NOT delegate Register or UnRegister calls to the
936  // SecondaryDelegate... Only pass them up to the parent
937  // class implementation on *this* object. The SecondaryDelegate
938  // is only held by us for delegating non-ref-counting calls
939  // to...
940  //
941  int secondaryIndent = 3;
942 
943  if (*mit != registerM && *mit != unRegisterM)
944  {
945  secondaryIndent = 3;
946 
947  EmitIndent(os, 2);
948  Emit(os, "if (this->SecondaryDelegate)\n");
949 
950  EmitIndent(os, 3);
951  Emit(os, "{\n");
952 
953  EmitIndent(os, 3);
954  if (!voidReturn)
955  {
956  Emit(os, "rv = ");
957  }
958  Emit(os, "this->SecondaryDelegate->");
959  Emit(os, (*mit)->GetName());
960  Emit(os, "(");
961 
962  for (argi= 0; argi<cArgs; ++argi)
963  {
964  Emit(os, GetArgName((*mit)->GetFunctionType(), argi));
965 
966  if (argi<cArgs-1)
967  {
968  Emit(os, ", ");
969  }
970  }
971  Emit(os, ");\n");
972 
973  EmitIndent(os, 3);
974  Emit(os, "}\n");
975 
976  EmitIndent(os, 2);
977  Emit(os, "else\n");
978 
979  EmitIndent(os, 3);
980  Emit(os, "{\n");
981  }
982  else
983  {
984  secondaryIndent = 2;
985  }
986 
987 
988  // Only call the base class if it's not a pure virtual. If it's a pure
989  // virtual, then the method we are in may be the only implementation.
990  // If that's the case (as in vtkCommand::Execute) then it's a mistake
991  // if the primary delegate has not already handled it.
992  //
993  if ((*mit)->GetPureVirtual())
994  {
995  EmitIndent(os, secondaryIndent);
996  Emit(os, "// pure virtual method in parent class...\n");
997 
998  if (*mit == registerM || *mit == unRegisterM)
999  {
1000  EmitIndent(os, secondaryIndent);
1001  Emit(os, "// Register and UnRegister methods should *not* be\n");
1002  EmitIndent(os, secondaryIndent);
1003  Emit(os, "// pure virtual methods in a shadowed class...\n");
1004 
1006  << "Register and UnRegister methods *cannot* be pure "
1007  << "virtual methods in a shadowed class..."
1008  );
1009  }
1010  }
1011  else
1012  {
1013  EmitIndent(os, secondaryIndent);
1014  if (!voidReturn)
1015  {
1016  Emit(os, "rv = ");
1017  }
1018  Emit(os, "this->");
1019  Emit(os, c->GetQualifiedName().c_str());
1020  Emit(os, "::");
1021  Emit(os, (*mit)->GetName());
1022  Emit(os, "(");
1023 
1024  for (argi= 0; argi<cArgs; ++argi)
1025  {
1026  Emit(os, GetArgName((*mit)->GetFunctionType(), argi));
1027 
1028  if (argi<cArgs-1)
1029  {
1030  Emit(os, ", ");
1031  }
1032  }
1033  Emit(os, ");\n");
1034  }
1035 
1036  if (*mit != registerM && *mit != unRegisterM)
1037  {
1038  EmitIndent(os, 3);
1039  Emit(os, "}\n");
1040  }
1041 
1042 
1043  EmitIndent(os, 2);
1044  Emit(os, "}\n");
1045 
1046 
1047  if (!voidReturn)
1048  {
1049  Emit(os, "\n");
1050 
1051  EmitIndent(os);
1052  Emit(os, "return rv;\n");
1053  }
1054 
1055  Emit(os, "}\n");
1056  }
1057 
1058  ++i;
1059  }
1060 
1061 
1062  // Constructor:
1063  //
1064  Emit(os, "\n");
1065  Emit(os, "\n");
1066  Emit(os, "//----------------------------------------------------------------------------\n");
1067  Emit(os, s.c_str());
1068  Emit(os, "::");
1069  Emit(os, s.c_str());
1070  Emit(os, "()\n");
1071  Emit(os, "{\n");
1072 
1073  // Initialize pointers to 0 and bool flags to false:
1074  //
1075  EmitIndent(os);
1076  Emit(os, "this->PrimaryDelegate = 0;\n");
1077 
1078  EmitIndent(os);
1079  Emit(os, "this->SecondaryDelegate = 0;\n");
1080 
1081  i = 0;
1082  for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
1083  mit != wrapped_methods.end(); ++mit)
1084  {
1085  if ((*mit)->GetVirtual())
1086  {
1087  EmitIndent(os);
1088  Emit(os, "this->CallingPrimary_");
1089  Emit(os, (*mit)->GetName());
1090  Emit(os, "_");
1091  EmitUint(os, i+1);
1092  Emit(os, " = false;\n");
1093  }
1094 
1095  ++i;
1096  }
1097 
1098  if (ClassIsA(c, "vtkObject"))
1099  {
1100  Emit(os, "\n");
1101  Emit(os, "#ifdef VTK_DEBUG_LEAKS\n");
1102 
1103  EmitIndent(os);
1104  Emit(os, "vtkDebugLeaks::ConstructClass(\"");
1105  Emit(os, c->GetName());
1106  Emit(os, "\");\n");
1107 
1108  Emit(os, "#endif\n");
1109  }
1110 
1111  Emit(os, "}\n");
1112 
1113 
1114  // Destructor:
1115  //
1116  Emit(os, "\n");
1117  Emit(os, "\n");
1118  Emit(os, "//----------------------------------------------------------------------------\n");
1119  Emit(os, s.c_str());
1120  Emit(os, "::~");
1121  Emit(os, s.c_str());
1122  Emit(os, "()\n");
1123  Emit(os, "{\n");
1124  EmitIndent(os);
1125  Emit(os, "this->DisconnectShadowDelegates();\n");
1126  Emit(os, "}\n");
1127 
1128 
1129  // And one extra export layer style function to create an instance of the
1130  // shadow class:
1131  //
1132  Emit(os, "\n");
1133  Emit(os, "\n");
1134  Emit(os, "//----------------------------------------------------------------------------\n");
1135  Emit(os, "extern \"C\" MUMMY_DLL_EXPORT\n");
1136 
1137  Emit(os, s.c_str());
1138  Emit(os, "* ");
1139  Emit(os, s.c_str());
1140  Emit(os, "_CreateShadow(");
1141  Emit(os, GetPrimaryDelegateCxxType(c).c_str());
1142  Emit(os, " primary)\n");
1143 
1144  Emit(os, "{\n");
1145 
1146  EmitIndent(os);
1147  Emit(os, s.c_str());
1148  Emit(os, "* rv = ");
1149  Emit(os, s.c_str());
1150  Emit(os, "::CreateShadow(primary);\n");
1151 
1152  EmitIndent(os);
1153  Emit(os, "return rv;\n");
1154 
1155  Emit(os, "}\n");
1156 }
1157 
1158 
1159 //----------------------------------------------------------------------------
1160 void MummyCsharpShadowLayerGenerator::EmitClassForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c)
1161 {
1162  // Gather wrapped elements:
1163  //
1164  gxsys_stl::vector<cable::Method*> wrapped_methods;
1165  cable::Method *factoryM = 0;
1166  cable::Method *disposalM = 0;
1167  cable::Method *registerM = 0;
1168  cable::Method *unRegisterM = 0;
1169 
1170  this->GetCsharpGenerator()->GatherWrappedMethods(c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM, true);
1171 
1172  // For the purposes of the shadow layer, make sure the Register and UnRegister
1173  // methods are emitted (same as any other wrapped method) in the shadow class:
1174  //
1175  wrapped_methods.insert(wrapped_methods.begin(), unRegisterM);
1176  wrapped_methods.insert(wrapped_methods.begin(), registerM);
1177 
1178  EmitClassDeclarationForShadowLayer(os, c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM);
1179 
1180  EmitClassImplementationForShadowLayer(os, c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM);
1181 }
bool IsChar(const cable::Type *t)
gxsys_stl::string GetShadowClassName(const cable::Class *c)
void Emit(gxsys_ios::ostream &os, const char *s)
virtual void EmitClassDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const gxsys_stl::vector< cable::Method * > &wrapped_methods, cable::Method *factoryM, cable::Method *disposalM, cable::Method *registerM, cable::Method *unRegisterM)
virtual const char * GetArgName(cable::FunctionType *ftype, unsigned int i)
gxsys_stl::string GetVariantTypeString(const cable::Type *t)
void EmitIndent(gxsys_ios::ostream &os, const unsigned int n)
void EmitUint(gxsys_ios::ostream &os, const unsigned int i)
bool ClassIsA(const cable::Class *c, const gxsys_stl::string &parent)
bool IsObject(const cable::Type *t)
virtual void EmitClassMethodDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const cable::Method *m, const unsigned int index, int indent, const char *implClassName)
virtual const char * GetArgName(cable::FunctionType *ftype, unsigned int i)
gxsys_stl::string GetVariantTypeCastingString(const cable::Type *t)
bool IsVoid(const cable::Type *t)
virtual void SetCsharpGenerator(MummyCsharpGenerator *generator)
gxsys_stl::string GetSecondaryDelegateCxxType(const cable::Class *c)
virtual const cable::Class * GetTargetClass()
Get the current target class.
#define LogError(n, m)
Definition: MummyLog.h:41
virtual void GatherWrappedMethods(const cable::Class *c, gxsys_stl::vector< cable::Method * > &wrapped_methods, cable::Method *&factoryM, cable::Method *&disposalM, cable::Method *&registerM, cable::Method *&unRegisterM, bool includeParentMethods)
virtual MummyCsharpGenerator * GetCsharpGenerator()
virtual void EmitClassForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c)
virtual void EmitClassImplementationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c, const gxsys_stl::vector< cable::Method * > &wrapped_methods, cable::Method *factoryM, cable::Method *disposalM, cable::Method *registerM, cable::Method *unRegisterM)
gxsys_stl::string GetVariantFundamentalTypeString(const cable::Type *t)
gxsys_stl::string GetPrimaryDelegateCxxType(const cable::Class *c)