mummy  1.0.2
MummyCsharpShadowLayerGenerator.cxx
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------
00002 //
00003 //  $Id: MummyCsharpShadowLayerGenerator.cxx 442 2009-04-03 19:47:41Z david.cole $
00004 //
00005 //  $Author: david.cole $
00006 //  $Date: 2009-04-03 15:47:41 -0400 (Fri, 03 Apr 2009) $
00007 //  $Revision: 442 $
00008 //
00009 //  Copyright (C) 2006-2007 Kitware, Inc.
00010 //
00011 //----------------------------------------------------------------------------
00012 
00013 #include "MummyCsharpShadowLayerGenerator.h"
00014 #include "MummyCsharpGenerator.h"
00015 #include "MummyLog.h"
00016 #include "MummySettings.h"
00017 
00018 #include "cableClass.h"
00019 #include "cableClassType.h"
00020 #include "cableFundamentalType.h"
00021 #include "cableFunctionType.h"
00022 #include "cableMethod.h"
00023 #include "cablePointerType.h"
00024 #include "cableType.h"
00025 
00026 #include "gxsys/ios/sstream"
00027 
00028 
00029 //----------------------------------------------------------------------------
00030 MummyCsharpShadowLayerGenerator::MummyCsharpShadowLayerGenerator()
00031 {
00032   this->CsharpGenerator = 0;
00033 }
00034 
00035 
00036 //----------------------------------------------------------------------------
00037 MummyCsharpShadowLayerGenerator::~MummyCsharpShadowLayerGenerator()
00038 {
00039 }
00040 
00041 
00042 //----------------------------------------------------------------------------
00043 bool MummyCsharpShadowLayerGenerator::GenerateWrappers()
00044 {
00045   this->EmitClassForShadowLayer(*GetStream(), GetTargetClass());
00046   return false;
00047 }
00048 
00049 
00050 //----------------------------------------------------------------------------
00051 MummyCsharpGenerator* MummyCsharpShadowLayerGenerator::GetCsharpGenerator()
00052 {
00053   return this->CsharpGenerator;
00054 }
00055 
00056 
00057 //----------------------------------------------------------------------------
00058 void MummyCsharpShadowLayerGenerator::SetCsharpGenerator(MummyCsharpGenerator* generator)
00059 {
00060   this->CsharpGenerator = generator;
00061 }
00062 
00063 
00064 //----------------------------------------------------------------------------
00065 const char *MummyCsharpShadowLayerGenerator::GetArgName(cable::FunctionType *ftype, unsigned int i)
00066 {
00067   return this->GetCsharpGenerator()->GetArgName(ftype, i);
00068 }
00069 
00070 
00071 //----------------------------------------------------------------------------
00072 gxsys_stl::string GetShadowClassName(const cable::Class *c)
00073 {
00074   gxsys_stl::string s(c->GetName());
00075   s += "Shadow";
00076   return s;
00077 }
00078 
00079 
00080 //----------------------------------------------------------------------------
00081 gxsys_stl::string GetPrimaryDelegateCxxType(const cable::Class *c)
00082 {
00083   return GetShadowClassName(c) + "_PrimaryType";
00084 }
00085 
00086 
00087 //----------------------------------------------------------------------------
00088 gxsys_stl::string GetSecondaryDelegateCxxType(const cable::Class *c)
00089 {
00090   return gxsys_stl::string(c->GetName()) + "*";
00091 }
00092 
00093 
00094 //----------------------------------------------------------------------------
00095 void MummyCsharpShadowLayerGenerator::EmitClassMethodDeclarationForShadowLayer(gxsys_ios::ostream &os, const cable::Class *, const cable::Method *m, const unsigned int, int indent, const char *implClassName)
00096 {
00097   cable::FunctionType *ft = m->GetFunctionType();
00098   unsigned int cArgs = ft->GetNumberOfArguments();
00099   unsigned int i = 0;
00100   cable::Type *argType = 0;
00101   cable::Type *retType = ft->GetReturns();
00102 
00103   EmitIndent(os, indent);
00104 
00105   // Context:
00106 //  Emit(os, "/* ");
00107 //  Emit(os, m->GetContext()->GetName());
00108 //  Emit(os, " */ ");
00109 
00110   // Abstract?
00111 //  if (m->GetPureVirtual())
00112 //    {
00113 //    Emit(os, "/* pure virtual */ ");
00114 //    }
00115 
00116   // Definitely virtual:
00117   if (m->GetVirtual() && !implClassName)
00118     {
00119     Emit(os, "virtual ");
00120     }
00121 
00122   // Return type:
00123   Emit(os, retType->GetCxxType().GetName().c_str());
00124   Emit(os, " ");
00125 
00126   // Class name colon colon:
00127   if (implClassName)
00128     {
00129     Emit(os, implClassName);
00130     Emit(os, "::");
00131     }
00132 
00133   // Method name:
00134   Emit(os, m->GetName());
00135 
00136   // Open args:
00137   Emit(os, "(");
00138 
00139   // The real args:
00140   for (i= 0; i<cArgs; ++i)
00141     {
00142     argType = ft->GetArgument(i);
00143 
00144     // arg "i":
00145     Emit(os, argType->GetCxxType().GetName().c_str());
00146     Emit(os, " ");
00147     Emit(os, GetArgName(ft, i));
00148 
00149     if (i<cArgs-1)
00150       {
00151       Emit(os, ", ");
00152       }
00153     }
00154 
00155   // Close args:
00156   Emit(os, ")");
00157 }
00158 
00159 
00160 //----------------------------------------------------------------------------
00161 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*)
00162 {
00163   unsigned int i = 0;
00164   gxsys_stl::string s(GetShadowClassName(c));
00165 
00166   if (ClassIsA(c, "vtkObject"))
00167     {
00168     Emit(os, "\n");
00169     Emit(os, "\n");
00170     Emit(os, "//----------------------------------------------------------------------------\n");
00171     Emit(os, "#include \"vtkDebugLeaks.h\"\n");
00172     }
00173 
00174   Emit(os, "\n");
00175   Emit(os, "\n");
00176   Emit(os, "//----------------------------------------------------------------------------\n");
00177 
00178   Emit(os, "#undef ");
00179   Emit(os, s.c_str());
00180   Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
00181   Emit(os, "\n");
00182   Emit(os, "#ifdef _MSC_VER\n");
00183   Emit(os, "#define ");
00184   Emit(os, s.c_str());
00185   Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
00186   Emit(os, "#endif\n");
00187   Emit(os, "\n");
00188   Emit(os, "#ifdef ");
00189   Emit(os, s.c_str());
00190   Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
00191   Emit(os, "#include \"windows.h\" // HRESULT, FAILED, E_UNEXPECTED\n");
00192   Emit(os, "#define ");
00193   Emit(os, s.c_str());
00194   Emit(os, "_PrimaryType IDispatch*\n");
00195   Emit(os, "#else\n");
00196   Emit(os, "#define ");
00197   Emit(os, s.c_str());
00198   Emit(os, "_PrimaryType void*\n");
00199   Emit(os, "#define HRESULT long\n");
00200   Emit(os, "#define FAILED(hr) ((HRESULT)(hr) < 0)\n");
00201   Emit(os, "#define E_UNEXPECTED ((HRESULT)0x8000FFFFL)\n");
00202   Emit(os, "#endif\n");
00203 
00204 
00205   Emit(os, "\n");
00206   Emit(os, "\n");
00207   Emit(os, "//----------------------------------------------------------------------------\n");
00208 
00209   Emit(os, "class ");
00210   Emit(os, s.c_str());
00211   Emit(os, " : public ");
00212   Emit(os, c->GetQualifiedName().c_str());
00213 
00214   // Abstract?
00215   //if (c->GetAbstract())
00216   //  {
00217   //  Emit(os, " /* abstract */");
00218   //  }
00219 
00220   Emit(os, "\n");
00221 
00222   Emit(os, "{\n");
00223   Emit(os, "public:\n");
00224 
00225   // Shadow class always has factory method and DisconnectShadowDelegates:
00226   //
00227   // The factory method is "create-and-connect" so that it can be made in
00228   // one "over-the-boundary" call from the wrapped layer:
00229   //
00230   EmitIndent(os);
00231   Emit(os, "static ");
00232   Emit(os, s.c_str());
00233   Emit(os, "* CreateShadow(");
00234   Emit(os, GetPrimaryDelegateCxxType(c).c_str());
00235   Emit(os, " primary);");
00236   Emit(os, "\n");
00237 
00238   EmitIndent(os);
00239   Emit(os, "void DisconnectShadowDelegates();");
00240   Emit(os, "\n");
00241 
00242   Emit(os, "\n");
00243 
00244   // And overrides of all the virtual wrapped methods (including the Register
00245   // and UnRegister methods, if any...)
00246   //
00247   i = 0;
00248   for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
00249     mit != wrapped_methods.end(); ++mit)
00250     {
00251     if ((*mit)->GetVirtual())
00252       {
00253       EmitClassMethodDeclarationForShadowLayer(os, c, *mit, i+1, 1, false);
00254       Emit(os, ";\n");
00255       }
00256     ++i;
00257     }
00258 
00259 
00260   Emit(os, "\n");
00261   Emit(os, "protected:\n");
00262   EmitIndent(os);
00263   Emit(os, s.c_str());
00264   Emit(os, "();\n");
00265   EmitIndent(os);
00266   Emit(os, "virtual ~");
00267   Emit(os, s.c_str());
00268   Emit(os, "();\n");
00269 
00270 
00271   Emit(os, "\n");
00272   Emit(os, "private:\n");
00273   EmitIndent(os);
00274   Emit(os, GetPrimaryDelegateCxxType(c).c_str());
00275   Emit(os, " PrimaryDelegate;");
00276   Emit(os, "\n");
00277   EmitIndent(os);
00278   Emit(os, GetSecondaryDelegateCxxType(c).c_str());
00279   Emit(os, " SecondaryDelegate;");
00280   Emit(os, "\n");
00281 
00282   // A bool flag for each virtual override indicating whether the shadow
00283   // class is currently calling that method on the primary delegate or not:
00284   //
00285   i = 0;
00286   for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
00287     mit != wrapped_methods.end(); ++mit)
00288     {
00289     if ((*mit)->GetVirtual())
00290       {
00291       EmitIndent(os);
00292       Emit(os, "bool CallingPrimary_");
00293       Emit(os, (*mit)->GetName());
00294       Emit(os, "_");
00295       EmitUint(os, i+1);
00296       Emit(os, ";\n");
00297       }
00298 
00299     ++i;
00300     }
00301 
00302   Emit(os, "};\n");
00303 }
00304 
00305 
00306 //----------------------------------------------------------------------------
00307 // The string returned from these Variant functions should be a valid V_ and
00308 // VT_ suffix for use with initializing/accessing a VARIANT variable of the
00309 // given type...
00310 //
00311 // For example, in the use case:
00312 //   VariantInit(&vargs[0]);
00313 //   V_VT(&vargs[0]) = VT_I4;
00314 //   V_I4(&vargs[0]) = (long) callData;
00315 // This function will receive a cable type representing the C++ type "long"
00316 // and return "I4"...
00317 //
00318 gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantFundamentalTypeString(const cable::Type *t)
00319 {
00320   gxsys_stl::string s;
00321 
00322   if (cable::Type::FundamentalTypeId == t->GetTypeId())
00323     {
00324     s = cable::FundamentalType::SafeDownCast(t)->GetTypeName();
00325 
00326     switch (cxx::FundamentalType::SafeDownCast(t->GetCxxType().GetType())->GetId())
00327       {
00328       case cxx::FundamentalType::UnsignedChar:
00329         s = "UI1";
00330       break;
00331 
00332       case cxx::FundamentalType::UnsignedShortInt:
00333         s = "UI2";
00334       break;
00335 
00336       case cxx::FundamentalType::UnsignedInt:
00337       case cxx::FundamentalType::UnsignedLongInt:
00338         s = "UI4";
00339       break;
00340 
00341       case cxx::FundamentalType::UnsignedLongLongInt:
00342         s = "UI8";
00343       break;
00344 
00345       case cxx::FundamentalType::SignedChar:
00346       case cxx::FundamentalType::Char:
00347         s = "I1";
00348       break;
00349 
00350       case cxx::FundamentalType::ShortInt:
00351         s = "I2";
00352       break;
00353 
00354       case cxx::FundamentalType::Int:
00355       case cxx::FundamentalType::LongInt:
00356         s = "I4";
00357       break;
00358 
00359       case cxx::FundamentalType::LongLongInt:
00360         s = "I8";
00361       break;
00362 
00363       case cxx::FundamentalType::Bool:
00364         s = "BOOL";
00365       break;
00366 
00367       case cxx::FundamentalType::Float:
00368         s = "R4";
00369       break;
00370 
00371       case cxx::FundamentalType::Double:
00372         s = "R8";
00373       break;
00374 
00375       //case cxx::FundamentalType::Void:
00376       //case cxx::FundamentalType::WChar_t:
00377       //case cxx::FundamentalType::LongDouble:
00378       //case cxx::FundamentalType::ComplexFloat:
00379       //case cxx::FundamentalType::ComplexDouble:
00380       //case cxx::FundamentalType::ComplexLongDouble:
00381       //case cxx::FundamentalType::NumberOfTypes:
00382       default:
00383       break;
00384       }
00385     }
00386 
00387   if (s == "")
00388     {
00389     LogError(me_InternalError,
00390       << "Unhandled variable type. GetVariantFundamentalTypeString returning the empty string...");
00391     }
00392 
00393   return s;
00394 }
00395 
00396 
00397 //----------------------------------------------------------------------------
00398 gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantTypeString(const cable::Type *t)
00399 {
00400   gxsys_stl::string s;
00401   cable::Type *nested_type = 0;
00402 
00403   switch (t->GetTypeId())
00404     {
00405     case cable::Type::EnumerationTypeId:
00406       s = "UI4";
00407     break;
00408 
00409     case cable::Type::FundamentalTypeId:
00410       s = GetVariantFundamentalTypeString(t);
00411     break;
00412 
00413     case cable::Type::ArrayTypeId:
00414       s = "ERROR_ArrayTypeId_not_yet_implemented";
00415       LogError(me_InternalError, << s.c_str());
00416     break;
00417 
00418     case cable::Type::ClassTypeId:
00419       s = "ERROR_passing_class__";
00420       s += cable::ClassType::SafeDownCast(t)->GetClass()->GetName();
00421       s += "__by_value_not_allowed";
00422       LogError(me_InternalError, << s.c_str());
00423     break;
00424 
00425     case cable::Type::PointerTypeId:
00426       nested_type = cable::PointerType::SafeDownCast(t)->GetTarget();
00427 
00428       // IntPtr maps to I4 on 32-bit windows and I8 on 64-bit windows...
00429       //
00430       if (IsObject(nested_type))
00431         {
00432         s = "I4";
00433         }
00434       else if (IsChar(nested_type))
00435         {
00436         s = "I4";
00437         }
00438       else if (IsVoid(nested_type))
00439         {
00440         s = "I4";
00441         }
00442       else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId())
00443         {
00444         s = "I4";
00445         }
00446       else if (cable::Type::PointerTypeId == nested_type->GetTypeId())
00447         {
00448         s = "I4 /* pointer */";
00449         }
00450       else
00451         {
00452         s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type";
00453         LogError(me_InternalError, << s.c_str());
00454         }
00455     break;
00456 
00457     case cable::Type::ReferenceTypeId:
00458       s = "ERROR_ReferenceTypeId_not_yet_implemented";
00459       LogError(me_InternalError, << s.c_str());
00460     break;
00461 
00462     case cable::Type::OffsetTypeId:
00463     case cable::Type::MethodTypeId:
00464     case cable::Type::FunctionTypeId:
00465     default:
00466       s = "ERROR_No_Variant_type_for_cable_Type_TypeId";
00467       LogError(me_InternalError, << s.c_str());
00468     break;
00469     }
00470 
00471   if (s == "")
00472     {
00473     LogError(me_InternalError,
00474       << "Unhandled variable type. GetVariantTypeString returning the empty string...");
00475     }
00476 
00477   return s;
00478 }
00479 
00480 
00481 //----------------------------------------------------------------------------
00482 gxsys_stl::string /* MummyCsharpShadowLayerGenerator:: */ GetVariantTypeCastingString(const cable::Type *t)
00483 {
00484   gxsys_stl::string s;
00485   cable::Type *nested_type = 0;
00486 
00487   switch (t->GetTypeId())
00488     {
00489     case cable::Type::EnumerationTypeId:
00490       s = "(unsigned int) ";
00491     break;
00492 
00493     case cable::Type::FundamentalTypeId:
00494       // No cast needed...
00495       s = "";
00496     break;
00497 
00498     case cable::Type::ArrayTypeId:
00499       s = "ERROR_ArrayTypeId_not_yet_implemented";
00500       LogError(me_InternalError, << s.c_str());
00501     break;
00502 
00503     case cable::Type::ClassTypeId:
00504       s = "ERROR_passing_class__";
00505       s += cable::ClassType::SafeDownCast(t)->GetClass()->GetName();
00506       s += "__by_value_not_allowed";
00507       LogError(me_InternalError, << s.c_str());
00508     break;
00509 
00510     case cable::Type::PointerTypeId:
00511       nested_type = cable::PointerType::SafeDownCast(t)->GetTarget();
00512 
00513       // IntPtr maps to I4 on 32-bit windows and I8 on 64-bit windows...
00514       //
00515       if (IsObject(nested_type))
00516         {
00517         s = "(int) ";
00518         }
00519       else if (IsChar(nested_type))
00520         {
00521         s = "(int) ";
00522         }
00523       else if (IsVoid(nested_type))
00524         {
00525         s = "(int) ";
00526         }
00527       else if (cable::Type::FundamentalTypeId == nested_type->GetTypeId())
00528         {
00529         s = "(int) ";
00530         }
00531       else if (cable::Type::PointerTypeId == nested_type->GetTypeId())
00532         {
00533         s = "(int) /* pointer */";
00534         }
00535       else
00536         {
00537         s = "ERROR_PointerTypeId_not_yet_implemented_for_nested_type";
00538         LogError(me_InternalError, << s.c_str());
00539         }
00540     break;
00541 
00542     case cable::Type::ReferenceTypeId:
00543       s = "ERROR_ReferenceTypeId_not_yet_implemented";
00544       LogError(me_InternalError, << s.c_str());
00545     break;
00546 
00547     case cable::Type::OffsetTypeId:
00548     case cable::Type::MethodTypeId:
00549     case cable::Type::FunctionTypeId:
00550     default:
00551       s = "ERROR_No_Variant_type_for_cable_Type_TypeId";
00552       LogError(me_InternalError, << s.c_str());
00553     break;
00554     }
00555 
00556   return s;
00557 }
00558 
00559 
00560 //----------------------------------------------------------------------------
00561 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)
00562 {
00563   unsigned int i = 0;
00564   gxsys_stl::string s(GetShadowClassName(c));
00565   gxsys_ios::ostringstream oss;
00566   gxsys_stl::string vargs;
00567 
00568   // Shadow class always has factory method and DisconnectShadowDelegates:
00569   //
00570   Emit(os, "\n");
00571   Emit(os, "\n");
00572   Emit(os, "//----------------------------------------------------------------------------\n");
00573   Emit(os, "/* static */\n");
00574   Emit(os, s.c_str());
00575   Emit(os, "* ");
00576   Emit(os, s.c_str());
00577   Emit(os, "::");
00578   Emit(os, "CreateShadow(");
00579   Emit(os, GetPrimaryDelegateCxxType(c).c_str());
00580   Emit(os, " primary)");
00581   Emit(os, "\n");
00582   Emit(os, "{\n");
00583 
00584   EmitIndent(os);
00585   Emit(os, s.c_str());
00586   Emit(os, "* rv = new ");
00587   Emit(os, s.c_str());
00588   Emit(os, ";\n");
00589 
00590   EmitIndent(os);
00591   Emit(os, "rv->PrimaryDelegate = primary;\n");
00592 
00593   EmitIndent(os);
00594   Emit(os, "rv->SecondaryDelegate = ");
00595   if (factoryM)
00596     {
00597     Emit(os, c->GetName());
00598     Emit(os, "::");
00599     Emit(os, factoryM->GetName());
00600     Emit(os, "()");
00601     }
00602   else
00603     {
00604     Emit(os, "0");
00605     }
00606   Emit(os, ";\n");
00607   Emit(os, "\n");
00608 
00609   EmitIndent(os);
00610   Emit(os, "if (rv->PrimaryDelegate)\n");
00611   EmitIndent(os, 2);
00612   Emit(os, "{\n");
00613   Emit(os, "#ifdef ");
00614   Emit(os, s.c_str());
00615   Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
00616   EmitIndent(os, 2);
00617   Emit(os, "rv->PrimaryDelegate->AddRef();\n");
00618   Emit(os, "#else\n");
00619   Emit(os, "#endif\n");
00620   EmitIndent(os, 2);
00621   Emit(os, "}\n");
00622   Emit(os, "\n");
00623 
00624   EmitIndent(os);
00625   Emit(os, "return rv;\n");
00626 
00627   Emit(os, "}\n");
00628 
00629   Emit(os, "\n");
00630   Emit(os, "\n");
00631   Emit(os, "//----------------------------------------------------------------------------\n");
00632   Emit(os, "void ");
00633   Emit(os, s.c_str());
00634   Emit(os, "::");
00635   Emit(os, "DisconnectShadowDelegates()");
00636   Emit(os, "\n");
00637   Emit(os, "{\n");
00638 
00639   EmitIndent(os);
00640   Emit(os, "if (this->PrimaryDelegate)\n");
00641   EmitIndent(os, 2);
00642   Emit(os, "{\n");
00643   Emit(os, "#ifdef ");
00644   Emit(os, s.c_str());
00645   Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
00646   EmitIndent(os, 2);
00647   Emit(os, "this->PrimaryDelegate->Release();\n");
00648   Emit(os, "#else\n");
00649   Emit(os, "#endif\n");
00650   EmitIndent(os, 2);
00651   Emit(os, "}\n");
00652   EmitIndent(os);
00653   Emit(os, "this->PrimaryDelegate = 0;\n");
00654   Emit(os, "\n");
00655 
00656   if (disposalM)
00657     {
00658     EmitIndent(os);
00659     Emit(os, "if (this->SecondaryDelegate)\n");
00660     EmitIndent(os, 2);
00661     Emit(os, "{\n");
00662     EmitIndent(os, 2);
00663     Emit(os, "this->SecondaryDelegate->");
00664     Emit(os, disposalM->GetName());
00665     Emit(os, "();\n");
00666     EmitIndent(os, 2);
00667     Emit(os, "}\n");
00668     }
00669 
00670   EmitIndent(os);
00671   Emit(os, "this->SecondaryDelegate = 0;\n");
00672 
00673   Emit(os, "\n");
00674   Emit(os, "}\n");
00675 
00676   // And overrides of all the virtual wrapped methods:
00677   //
00678   i = 0;
00679 
00680   for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
00681     mit != wrapped_methods.end(); ++mit)
00682     {
00683     if ((*mit)->GetVirtual())
00684       {
00685       unsigned int argi = 0;
00686       unsigned int cArgs = (*mit)->GetFunctionType()->GetNumberOfArguments();
00687       cable::Type *retType = (*mit)->GetFunctionType()->GetReturns();
00688       bool voidReturn = false;
00689       if (IsVoid(retType))
00690         {
00691         voidReturn = true;
00692         }
00693 
00694       Emit(os, "\n");
00695       Emit(os, "\n");
00696       Emit(os, "//----------------------------------------------------------------------------\n");
00697       EmitClassMethodDeclarationForShadowLayer(os, c, *mit, i+1, 0, s.c_str());
00698       Emit(os, "\n");
00699       Emit(os, "{\n");
00700 
00701       if (!voidReturn)
00702         {
00703         EmitIndent(os);
00704         Emit(os, retType->GetCxxType().GetName().c_str());
00705         Emit(os, " rv = ");
00706         if (cable::Type::PointerTypeId == retType->GetTypeId())
00707           {
00708           Emit(os, "0");
00709           }
00710         else if (cable::Type::FundamentalTypeId == retType->GetTypeId())
00711           {
00712           Emit(os, "(");
00713           Emit(os, retType->GetCxxType().GetName().c_str());
00714           Emit(os, ") 0");
00715           }
00716         else
00717           {
00718           Emit(os, retType->GetCxxType().GetName().c_str());
00719           Emit(os, "()");
00720           }
00721         Emit(os, ";\n");
00722         }
00723 
00724       EmitIndent(os);
00725       Emit(os, "HRESULT msl_hr = E_UNEXPECTED;\n");
00726       Emit(os, "\n");
00727 
00728       EmitIndent(os);
00729       Emit(os, "if (this->PrimaryDelegate && !this->CallingPrimary_");
00730       Emit(os, (*mit)->GetName());
00731       Emit(os, "_");
00732       EmitUint(os, i+1);
00733       Emit(os, ")\n");
00734 
00735       EmitIndent(os, 2);
00736       Emit(os, "{\n");
00737 
00738       EmitIndent(os, 2);
00739       Emit(os, "this->CallingPrimary_");
00740       Emit(os, (*mit)->GetName());
00741       Emit(os, "_");
00742       EmitUint(os, i+1);
00743       Emit(os, " = true;\n");
00744       Emit(os, "\n");
00745 
00746       Emit(os, "#ifdef ");
00747       Emit(os, s.c_str());
00748       Emit(os, "_USE_IDISPATCH_AS_PRIMARY\n");
00749       EmitIndent(os, 2);
00750       Emit(os, "IDispatch *msl_pDisp = (IDispatch *) this->PrimaryDelegate;\n");
00751       EmitIndent(os, 2);
00752       Emit(os, "msl_pDisp->AddRef();\n");
00753       Emit(os, "\n");
00754       EmitIndent(os, 2);
00755       Emit(os, "DISPID msl_dispid = (DISPID) -1;\n");
00756 
00757       EmitIndent(os, 2);
00758       Emit(os, "OLECHAR *msl_name = L\"");
00759       Emit(os, (*mit)->GetName());
00760       Emit(os, "\";\n");
00761 
00762       if (cArgs!=0)
00763         {
00764         EmitIndent(os, 2);
00765         Emit(os, "VARIANTARG msl_vargs[");
00766         oss.rdbuf()->str("");
00767         oss << cArgs << gxsys_ios::ends;
00768         vargs = oss.str();
00769         Emit(os, vargs.c_str());
00770         Emit(os, "];\n");
00771         }
00772 
00773       EmitIndent(os, 2);
00774       Emit(os, "DISPPARAMS msl_params;\n");
00775       EmitIndent(os, 2);
00776       Emit(os, "VARIANT msl_result;\n");
00777       EmitIndent(os, 2);
00778       Emit(os, "EXCEPINFO msl_excep;\n");
00779       EmitIndent(os, 2);
00780       Emit(os, "UINT msl_arg = (UINT) -1;\n");
00781       Emit(os, "\n");
00782       EmitIndent(os, 2);
00783       Emit(os, "msl_hr = msl_pDisp->GetIDsOfNames(\n");
00784       EmitIndent(os, 3);
00785       Emit(os, "IID_NULL,\n");
00786       EmitIndent(os, 3);
00787       Emit(os, "&msl_name,\n");
00788       EmitIndent(os, 3);
00789       Emit(os, "1,\n");
00790       EmitIndent(os, 3);
00791       Emit(os, "LOCALE_USER_DEFAULT,\n");
00792       EmitIndent(os, 3);
00793       Emit(os, "&msl_dispid);\n");
00794       Emit(os, "\n");
00795 
00796       EmitIndent(os, 2);
00797       Emit(os, "if (SUCCEEDED(msl_hr))\n");
00798       EmitIndent(os, 3);
00799       Emit(os, "{\n");
00800 
00801       for (argi= 0; argi<cArgs; ++argi)
00802         {
00803         oss.rdbuf()->str("");
00804         oss << "&msl_vargs[" << (cArgs-1-argi) << "]" << gxsys_ios::ends;
00805         vargs = oss.str();
00806 
00807         EmitIndent(os, 3);
00808         Emit(os, "VariantInit(");
00809         Emit(os, vargs.c_str());
00810         Emit(os, ");\n");
00811 
00812         EmitIndent(os, 3);
00813         Emit(os, "V_VT(");
00814         Emit(os, vargs.c_str());
00815         Emit(os, ") = VT_");
00816         Emit(os, GetVariantTypeString((*mit)->GetFunctionType()->GetArgument(argi)).c_str());
00817         Emit(os, ";\n");
00818 
00819         EmitIndent(os, 3);
00820         Emit(os, "V_");
00821         Emit(os, GetVariantTypeString((*mit)->GetFunctionType()->GetArgument(argi)).c_str());
00822         Emit(os, "(");
00823         Emit(os, vargs.c_str());
00824         Emit(os, ") = ");
00825         Emit(os, GetVariantTypeCastingString((*mit)->GetFunctionType()->GetArgument(argi)).c_str());
00826         Emit(os, GetArgName((*mit)->GetFunctionType(), argi));
00827         Emit(os, ";\n");
00828 
00829         Emit(os, "\n");
00830         }
00831 
00832       EmitIndent(os, 3);
00833       Emit(os, "msl_params.rgvarg = ");
00834       if (0 == cArgs)
00835         {
00836         Emit(os, "0");
00837         }
00838       else
00839         {
00840         Emit(os, "&msl_vargs[0]");
00841         }
00842       Emit(os, ";\n");
00843       EmitIndent(os, 3);
00844       Emit(os, "msl_params.rgdispidNamedArgs = 0;\n");
00845       EmitIndent(os, 3);
00846       Emit(os, "msl_params.cArgs = ");
00847       if (0 == cArgs)
00848         {
00849         Emit(os, "0");
00850         }
00851       else
00852         {
00853         Emit(os, "sizeof(msl_vargs)/sizeof(msl_vargs[0])");
00854         }
00855       Emit(os, ";\n");
00856       EmitIndent(os, 3);
00857       Emit(os, "msl_params.cNamedArgs = 0;\n");
00858       Emit(os, "\n");
00859       EmitIndent(os, 3);
00860       Emit(os, "VariantInit(&msl_result);\n");
00861       Emit(os, "\n");
00862       EmitIndent(os, 3);
00863       Emit(os, "memset(&msl_excep, 0, sizeof(msl_excep));\n");
00864       Emit(os, "\n");
00865       EmitIndent(os, 3);
00866       Emit(os, "msl_hr = msl_pDisp->Invoke(msl_dispid, IID_NULL, LOCALE_USER_DEFAULT,\n");
00867       EmitIndent(os, 4);
00868       Emit(os, "DISPATCH_METHOD, &msl_params, &msl_result, &msl_excep, &msl_arg);\n");
00869       Emit(os, "\n");
00870 
00871       if (!voidReturn)
00872         {
00873         EmitIndent(os, 3);
00874         Emit(os, "if (SUCCEEDED(msl_hr))\n");
00875         EmitIndent(os, 4);
00876         Emit(os, "{\n");
00877         EmitIndent(os, 4);
00878         Emit(os, "rv = (");
00879         Emit(os, retType->GetCxxType().GetName().c_str());
00880         Emit(os, ") V_");
00881         Emit(os, GetVariantTypeString(retType).c_str());
00882         Emit(os, "(&msl_result);\n");
00883         EmitIndent(os, 4);
00884         Emit(os, "}\n");
00885         Emit(os, "\n");
00886         }
00887 
00888       EmitIndent(os, 3);
00889       Emit(os, "VariantClear(&msl_result);\n");
00890 
00891       for (argi= 0; argi<cArgs; ++argi)
00892         {
00893         oss.rdbuf()->str("");
00894         oss << "&msl_vargs[" << argi << "]" << gxsys_ios::ends;
00895         vargs = oss.str();
00896 
00897         EmitIndent(os, 3);
00898         Emit(os, "VariantClear(");
00899         Emit(os, vargs.c_str());
00900         Emit(os, ");\n");
00901         }
00902 
00903       EmitIndent(os, 3);
00904       Emit(os, "}\n");
00905       Emit(os, "\n");
00906 
00907       EmitIndent(os, 2);
00908       Emit(os, "msl_pDisp->Release();\n");
00909       Emit(os, "#else\n");
00910       Emit(os, "#endif\n");
00911       Emit(os, "\n");
00912 
00913       EmitIndent(os, 2);
00914       Emit(os, "this->CallingPrimary_");
00915       Emit(os, (*mit)->GetName());
00916       Emit(os, "_");
00917       EmitUint(os, i+1);
00918       Emit(os, " = false;\n");
00919 
00920       EmitIndent(os, 2);
00921       Emit(os, "}\n");
00922       Emit(os, "\n");
00923 
00924 
00925       EmitIndent(os);
00926       Emit(os, "if (FAILED(msl_hr) || this->CallingPrimary_");
00927       Emit(os, (*mit)->GetName());
00928       Emit(os, "_");
00929       EmitUint(os, i+1);
00930       Emit(os, ")\n");
00931 
00932       EmitIndent(os, 2);
00933       Emit(os, "{\n");
00934 
00935       // Do NOT delegate Register or UnRegister calls to the
00936       // SecondaryDelegate... Only pass them up to the parent
00937       // class implementation on *this* object. The SecondaryDelegate
00938       // is only held by us for delegating non-ref-counting calls
00939       // to...
00940       //
00941       int secondaryIndent = 3;
00942 
00943       if (*mit != registerM && *mit != unRegisterM)
00944         {
00945         secondaryIndent = 3;
00946 
00947         EmitIndent(os, 2);
00948         Emit(os, "if (this->SecondaryDelegate)\n");
00949 
00950         EmitIndent(os, 3);
00951         Emit(os, "{\n");
00952 
00953         EmitIndent(os, 3);
00954         if (!voidReturn)
00955           {
00956           Emit(os, "rv = ");
00957           }
00958         Emit(os, "this->SecondaryDelegate->");
00959         Emit(os, (*mit)->GetName());
00960         Emit(os, "(");
00961 
00962         for (argi= 0; argi<cArgs; ++argi)
00963           {
00964           Emit(os, GetArgName((*mit)->GetFunctionType(), argi));
00965 
00966           if (argi<cArgs-1)
00967             {
00968             Emit(os, ", ");
00969             }
00970           }
00971         Emit(os, ");\n");
00972 
00973         EmitIndent(os, 3);
00974         Emit(os, "}\n");
00975 
00976         EmitIndent(os, 2);
00977         Emit(os, "else\n");
00978 
00979         EmitIndent(os, 3);
00980         Emit(os, "{\n");
00981         }
00982       else
00983         {
00984         secondaryIndent = 2;
00985         }
00986 
00987 
00988       // Only call the base class if it's not a pure virtual. If it's a pure
00989       // virtual, then the method we are in may be the only implementation.
00990       // If that's the case (as in vtkCommand::Execute) then it's a mistake
00991       // if the primary delegate has not already handled it.
00992       //
00993       if ((*mit)->GetPureVirtual())
00994         {
00995         EmitIndent(os, secondaryIndent);
00996         Emit(os, "// pure virtual method in parent class...\n");
00997 
00998         if (*mit == registerM || *mit == unRegisterM)
00999           {
01000           EmitIndent(os, secondaryIndent);
01001           Emit(os, "// Register and UnRegister methods should *not* be\n");
01002           EmitIndent(os, secondaryIndent);
01003           Emit(os, "// pure virtual methods in a shadowed class...\n");
01004 
01005           LogError(me_PureVirtualMethodNotAllowed,
01006             << "Register and UnRegister methods *cannot* be pure "
01007             << "virtual methods in a shadowed class..."
01008             );
01009           }
01010         }
01011       else
01012         {
01013         EmitIndent(os, secondaryIndent);
01014         if (!voidReturn)
01015           {
01016           Emit(os, "rv = ");
01017           }
01018         Emit(os, "this->");
01019         Emit(os, c->GetQualifiedName().c_str());
01020         Emit(os, "::");
01021         Emit(os, (*mit)->GetName());
01022         Emit(os, "(");
01023 
01024         for (argi= 0; argi<cArgs; ++argi)
01025           {
01026           Emit(os, GetArgName((*mit)->GetFunctionType(), argi));
01027 
01028           if (argi<cArgs-1)
01029             {
01030             Emit(os, ", ");
01031             }
01032           }
01033         Emit(os, ");\n");
01034         }
01035 
01036       if (*mit != registerM && *mit != unRegisterM)
01037         {
01038         EmitIndent(os, 3);
01039         Emit(os, "}\n");
01040         }
01041 
01042 
01043       EmitIndent(os, 2);
01044       Emit(os, "}\n");
01045 
01046 
01047       if (!voidReturn)
01048         {
01049         Emit(os, "\n");
01050 
01051         EmitIndent(os);
01052         Emit(os, "return rv;\n");
01053         }
01054 
01055       Emit(os, "}\n");
01056       }
01057 
01058     ++i;
01059     }
01060 
01061 
01062   // Constructor:
01063   //
01064   Emit(os, "\n");
01065   Emit(os, "\n");
01066   Emit(os, "//----------------------------------------------------------------------------\n");
01067   Emit(os, s.c_str());
01068   Emit(os, "::");
01069   Emit(os, s.c_str());
01070   Emit(os, "()\n");
01071   Emit(os, "{\n");
01072 
01073   // Initialize pointers to 0 and bool flags to false:
01074   //
01075   EmitIndent(os);
01076   Emit(os, "this->PrimaryDelegate = 0;\n");
01077 
01078   EmitIndent(os);
01079   Emit(os, "this->SecondaryDelegate = 0;\n");
01080 
01081   i = 0;
01082   for (gxsys_stl::vector<cable::Method*>::const_iterator mit = wrapped_methods.begin();
01083     mit != wrapped_methods.end(); ++mit)
01084     {
01085     if ((*mit)->GetVirtual())
01086       {
01087       EmitIndent(os);
01088       Emit(os, "this->CallingPrimary_");
01089       Emit(os, (*mit)->GetName());
01090       Emit(os, "_");
01091       EmitUint(os, i+1);
01092       Emit(os, " = false;\n");
01093       }
01094 
01095     ++i;
01096     }
01097 
01098   if (ClassIsA(c, "vtkObject"))
01099     {
01100     Emit(os, "\n");
01101     Emit(os, "#ifdef VTK_DEBUG_LEAKS\n");
01102 
01103     EmitIndent(os);
01104     Emit(os, "vtkDebugLeaks::ConstructClass(\"");
01105     Emit(os, c->GetName());
01106     Emit(os, "\");\n");
01107 
01108     Emit(os, "#endif\n");
01109     }
01110 
01111   Emit(os, "}\n");
01112 
01113 
01114   // Destructor:
01115   //
01116   Emit(os, "\n");
01117   Emit(os, "\n");
01118   Emit(os, "//----------------------------------------------------------------------------\n");
01119   Emit(os, s.c_str());
01120   Emit(os, "::~");
01121   Emit(os, s.c_str());
01122   Emit(os, "()\n");
01123   Emit(os, "{\n");
01124   EmitIndent(os);
01125   Emit(os, "this->DisconnectShadowDelegates();\n");
01126   Emit(os, "}\n");
01127 
01128 
01129   // And one extra export layer style function to create an instance of the
01130   // shadow class:
01131   //
01132   Emit(os, "\n");
01133   Emit(os, "\n");
01134   Emit(os, "//----------------------------------------------------------------------------\n");
01135   Emit(os, "extern \"C\" MUMMY_DLL_EXPORT\n");
01136 
01137   Emit(os, s.c_str());
01138   Emit(os, "* ");
01139   Emit(os, s.c_str());
01140   Emit(os, "_CreateShadow(");
01141   Emit(os, GetPrimaryDelegateCxxType(c).c_str());
01142   Emit(os, " primary)\n");
01143 
01144   Emit(os, "{\n");
01145 
01146   EmitIndent(os);
01147   Emit(os, s.c_str());
01148   Emit(os, "* rv = ");
01149   Emit(os, s.c_str());
01150   Emit(os, "::CreateShadow(primary);\n");
01151 
01152   EmitIndent(os);
01153   Emit(os, "return rv;\n");
01154 
01155   Emit(os, "}\n");
01156 }
01157 
01158 
01159 //----------------------------------------------------------------------------
01160 void MummyCsharpShadowLayerGenerator::EmitClassForShadowLayer(gxsys_ios::ostream &os, const cable::Class *c)
01161 {
01162   // Gather wrapped elements:
01163   //
01164   gxsys_stl::vector<cable::Method*> wrapped_methods;
01165   cable::Method *factoryM = 0;
01166   cable::Method *disposalM = 0;
01167   cable::Method *registerM = 0;
01168   cable::Method *unRegisterM = 0;
01169 
01170   this->GetCsharpGenerator()->GatherWrappedMethods(c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM, true);
01171 
01172   // For the purposes of the shadow layer, make sure the Register and UnRegister
01173   // methods are emitted (same as any other wrapped method) in the shadow class:
01174   //
01175   wrapped_methods.insert(wrapped_methods.begin(), unRegisterM);
01176   wrapped_methods.insert(wrapped_methods.begin(), registerM);
01177 
01178   EmitClassDeclarationForShadowLayer(os, c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM);
01179 
01180   EmitClassImplementationForShadowLayer(os, c, wrapped_methods, factoryM, disposalM, registerM, unRegisterM);
01181 }