/* ----------------------------------------------------------------------------- * csharp.cxx * * CSharp wrapper module. * * Author(s) : William Fulton * Neil Cawse * * Copyright (C) 1999-2002. The University of Chicago * See the file LICENSE for information on usage and redistribution. * ----------------------------------------------------------------------------- */ char cvsroot_csharp_cxx[] = "$Header$"; #include // for INT_MAX #include "swigmod.h" #include "cparse.h" #include class CSHARP : public Language { static const char *usage; const String *empty_string; const String *public_string; const String *protected_string; Hash *swig_types_hash; File *f_runtime; File *f_header; File *f_wrappers; File *f_init; List *filenames_list; bool proxy_flag; // Flag for generating proxy classes bool native_function_flag; // Flag for when wrapping a native function bool enum_constant_flag; // Flag for when wrapping an enum or constant bool static_flag; // Flag for when wrapping a static functions or member variables bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const bool global_variable_flag; // Flag for when wrapping a global variable bool old_variable_names; // Flag for old style variable names in the intermediary class bool generate_property_declaration_flag; // Flag for generating properties String *imclass_name; // intermediary class name String *module_class_name; // module class name String *imclass_class_code; // intermediary class code String *proxy_class_def; String *proxy_class_code; String *module_class_code; String *proxy_class_name; String *variable_name; //Name of a variable being wrapped String *proxy_class_constants_code; String *module_class_constants_code; String *enum_code; String *dllimport; // DllImport attribute name String *namespce; // Optional namespace name String *imclass_imports; //intermediary class imports from %pragma String *module_imports; //module imports from %pragma String *imclass_baseclass; //inheritance for intermediary class class from %pragma String *module_baseclass; //inheritance for module class from %pragma String *imclass_interfaces; //interfaces for intermediary class class from %pragma String *module_interfaces; //interfaces for module class from %pragma String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma String *module_class_modifiers; //class modifiers for module class overriden by %pragma String *upcasts_code; //C++ casts for inheritance hierarchies C++ code String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code String *destructor_call; //C++ destructor call if any enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum }; public: /* ----------------------------------------------------------------------------- * CSHARP() * ----------------------------------------------------------------------------- */ CSHARP() : empty_string(NewString("")), public_string(NewString("public")), protected_string(NewString("protected")), swig_types_hash(NULL), f_runtime(NULL), f_header(NULL), f_wrappers(NULL), f_init(NULL), filenames_list(NULL), proxy_flag(true), native_function_flag(false), enum_constant_flag(false), static_flag(false), variable_wrapper_flag(false), wrapping_member_flag(false), global_variable_flag(false), old_variable_names (false), generate_property_declaration_flag(false), imclass_name(NULL), module_class_name(NULL), imclass_class_code(NULL), proxy_class_def(NULL), proxy_class_code(NULL), module_class_code(NULL), proxy_class_name(NULL), variable_name(NULL), proxy_class_constants_code(NULL), module_class_constants_code(NULL), enum_code(NULL), dllimport(NULL), namespce(NULL), imclass_imports(NULL), module_imports(NULL), imclass_baseclass(NULL), module_baseclass(NULL), imclass_interfaces(NULL), module_interfaces(NULL), imclass_class_modifiers(NULL), module_class_modifiers(NULL), upcasts_code(NULL), imclass_cppcasts_code(NULL), destructor_call(NULL) { } /* ----------------------------------------------------------------------------- * getProxyName() * * Test to see if a type corresponds to something wrapped with a proxy class * Return NULL if not otherwise the proxy class name * ----------------------------------------------------------------------------- */ String *getProxyName(SwigType *t) { if (proxy_flag) { Node *n = classLookup(t); if (n) { return Getattr(n,"sym:name"); } } return NULL; } /* ------------------------------------------------------------ * main() * ------------------------------------------------------------ */ virtual void main(int argc, char *argv[]) { SWIG_library_directory("csharp"); // Look for certain command line options for (int i = 1; i < argc; i++) { if (argv[i]) { if (strcmp(argv[i],"-dllimport") == 0) { if (argv[i+1]) { dllimport = NewString(""); Printf(dllimport, argv[i+1]); Swig_mark_arg(i); Swig_mark_arg(i+1); i++; } else { Swig_arg_error(); } } else if (strcmp(argv[i],"-namespace") == 0) { if (argv[i+1]) { namespce = NewString(""); Printf(namespce, argv[i+1]); Swig_mark_arg(i); Swig_mark_arg(i+1); i++; } else { Swig_arg_error(); } } else if ((strcmp(argv[i],"-noproxy") == 0)) { Swig_mark_arg(i); proxy_flag = false; } else if (strcmp(argv[i],"-oldvarnames") == 0) { Swig_mark_arg(i); old_variable_names = true; } else if (strcmp(argv[i],"-help") == 0) { Printf(stdout,"%s\n", usage); } } } // Add a symbol to the parser for conditional compilation Preprocessor_define("SWIGCSHARP 1",0); // Add typemap definitions SWIG_typemap_lang("csharp"); SWIG_config_file("csharp.swg"); allow_overloading(); } /* --------------------------------------------------------------------- * top() * --------------------------------------------------------------------- */ virtual int top(Node *n) { // Get any options set in the module directive Node* optionsnode = Getattr( Getattr(n,"module"), "options"); if (optionsnode) { if (Getattr(optionsnode,"imclassname")) imclass_name = Copy(Getattr(optionsnode,"imclassname")); } /* Initialize all of the output files */ String *outfile = Getattr(n,"outfile"); f_runtime = NewFile(outfile,"w"); if (!f_runtime) { FileErrorDisplay(outfile); SWIG_exit(EXIT_FAILURE); } f_init = NewString(""); f_header = NewString(""); f_wrappers = NewString(""); /* Register file targets with the SWIG file handler */ Swig_register_filebyname("header",f_header); Swig_register_filebyname("wrapper",f_wrappers); Swig_register_filebyname("runtime",f_runtime); Swig_register_filebyname("init",f_init); swig_types_hash = NewHash(); filenames_list = NewList(); // Make the intermediary class and module class names. The intermediary class name can be set in the module directive. if (!imclass_name) { imclass_name = NewStringf("%sPINVOKE", Getattr(n,"name")); module_class_name = Copy(Getattr(n,"name")); } else { // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution if (Cmp(imclass_name, Getattr(n,"name")) == 0) module_class_name = NewStringf("%sModule", Getattr(n,"name")); else module_class_name = Copy(Getattr(n,"name")); } imclass_class_code = NewString(""); proxy_class_def = NewString(""); proxy_class_code = NewString(""); module_class_constants_code = NewString(""); imclass_baseclass = NewString(""); imclass_interfaces = NewString(""); imclass_class_modifiers = NewString(""); module_class_code = NewString(""); module_baseclass = NewString(""); module_interfaces = NewString(""); module_imports = NewString(""); module_class_modifiers = NewString(""); imclass_imports = NewString(""); imclass_cppcasts_code = NewString(""); upcasts_code = NewString(""); if (!namespce) namespce = NewString(""); if (!dllimport) dllimport = Copy(module_class_name); Swig_banner(f_runtime); // Print the SWIG banner message String *wrapper_name = NewString(""); Printf(wrapper_name, "CSharp_%%f", imclass_name); Swig_name_register((char*)"wrapper", Char(wrapper_name)); if (old_variable_names) { Swig_name_register((char*)"set", (char*)"set_%v"); Swig_name_register((char*)"get", (char*)"get_%v"); } Delete(wrapper_name); Printf(f_wrappers,"\n#ifdef __cplusplus\n"); Printf(f_wrappers,"extern \"C\" {\n"); Printf(f_wrappers,"#endif\n\n"); /* Emit code */ Language::top(n); // Generate the intermediary class { String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name); File *f_im = NewFile(filen,"w"); if(!f_im) { FileErrorDisplay(filen); SWIG_exit(EXIT_FAILURE); } Append(filenames_list, Copy(filen)); Delete(filen); filen = NULL; // Start writing out the intermediary class file emitBanner(f_im); if(Len(namespce) > 0) Printf(f_im, "namespace %s {\n", namespce); if(imclass_imports) Printf(f_im, "%s\n", imclass_imports); if (Len(imclass_class_modifiers) > 0) Printf(f_im, "%s ", imclass_class_modifiers); Printf(f_im, "%s ", imclass_name); if (imclass_baseclass && *Char(imclass_baseclass)) Printf(f_im, ": %s ", imclass_baseclass); if (Len(imclass_interfaces) > 0) Printv(f_im, "implements ", imclass_interfaces, " ", NIL); Printf(f_im, "{\n"); // Add the intermediary class methods Replaceall(imclass_class_code, "$module", module_class_name); Replaceall(imclass_class_code, "$imclassname", imclass_name); Replaceall(imclass_class_code, "$dllimport", dllimport); Printv(f_im, imclass_class_code, NIL); Printv(f_im, imclass_cppcasts_code, NIL); // Finish off the class Printf(f_im, "}\n"); Printf(f_im, Len(namespce) > 0 ? "\n}\n" : ""); Close(f_im); } // Generate the C# module class { String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name); File *f_module = NewFile(filen,"w"); if(!f_module) { FileErrorDisplay(filen); SWIG_exit(EXIT_FAILURE); } Append(filenames_list, Copy(filen)); Delete(filen); filen = NULL; // Start writing out the module class file emitBanner(f_module); if(Len(namespce) > 0) Printf(f_module, "namespace %s {\n", namespce); if(module_imports) Printf(f_module, "%s\n", module_imports); if (Len(module_class_modifiers) > 0) Printf(f_module, "%s ", module_class_modifiers); Printf(f_module, "%s ", module_class_name); if (module_baseclass && *Char(module_baseclass)) Printf(f_module, ": %s ", module_baseclass); if (Len(module_interfaces) > 0) Printv(f_module, "implements ", module_interfaces, " ", NIL); Printf(f_module, "{\n"); Replaceall(module_class_code, "$module", module_class_name); Replaceall(module_class_constants_code, "$module", module_class_name); Replaceall(module_class_code, "$imclassname", imclass_name); Replaceall(module_class_constants_code, "$imclassname", imclass_name); Replaceall(module_class_code, "$dllimport", dllimport); Replaceall(module_class_constants_code, "$dllimport", dllimport); // Add the wrapper methods Printv(f_module, module_class_code, NIL); // Write out all the global constants Printv(f_module, module_class_constants_code, NIL); // Finish off the class Printf(f_module, "}\n"); Printf(f_module, Len(namespce) > 0 ? "\n}\n" : ""); Close(f_module); } if(upcasts_code) Printv(f_wrappers,upcasts_code,NIL); Printf(f_wrappers,"#ifdef __cplusplus\n"); Printf(f_wrappers,"}\n"); Printf(f_wrappers,"#endif\n"); // Output a C# type wrapper class for each SWIG type for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) { emitTypeWrapperClass(swig_type.key, swig_type.item); } // Check for overwriting file problems on filesystems that are case insensitive Iterator it1; Iterator it2; for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) { String *item1_lower = Swig_string_lower(it1.item); for (it2 = Next(it1); it2.item; it2 = Next(it2)) { String *item2_lower = Swig_string_lower(it2.item); if (it1.item && it2.item) { if (Strcmp(item1_lower, item2_lower) == 0) { Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number, "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as " "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item); } } Delete(item2_lower); } Delete(item1_lower); } Delete(swig_types_hash); swig_types_hash = NULL; Delete(filenames_list); filenames_list = NULL; Delete(imclass_name); imclass_name = NULL; Delete(imclass_class_code); imclass_class_code = NULL; Delete(proxy_class_def); proxy_class_def = NULL; Delete(proxy_class_code); proxy_class_code = NULL; Delete(module_class_constants_code); module_class_constants_code = NULL; Delete(imclass_baseclass); imclass_baseclass = NULL; Delete(imclass_interfaces); imclass_interfaces = NULL; Delete(imclass_class_modifiers); imclass_class_modifiers = NULL; Delete(module_class_name); module_class_name = NULL; Delete(module_class_code); module_class_code = NULL; Delete(module_baseclass); module_baseclass = NULL; Delete(module_interfaces); module_interfaces = NULL; Delete(module_imports); module_imports = NULL; Delete(module_class_modifiers); module_class_modifiers = NULL; Delete(imclass_imports); imclass_imports = NULL; Delete(imclass_cppcasts_code); imclass_cppcasts_code = NULL; Delete(upcasts_code); upcasts_code = NULL; Delete(namespce); namespce = NULL; /* Close all of the files */ Dump(f_header,f_runtime); Dump(f_wrappers,f_runtime); Wrapper_pretty_print(f_init,f_runtime); Delete(f_header); Delete(f_wrappers); Delete(f_init); Close(f_runtime); Delete(f_runtime); return SWIG_OK; } /* ----------------------------------------------------------------------------- * emitBanner() * ----------------------------------------------------------------------------- */ void emitBanner(File *f) { Printf(f, "/* ----------------------------------------------------------------------------\n"); Printf(f, " * This file was automatically generated by SWIG (http://www.swig.org).\n"); Printf(f, " * Version %s\n", PACKAGE_VERSION); Printf(f, " *\n"); Printf(f, " * Do not make changes to this file unless you know what you are doing--modify\n"); Printf(f, " * the SWIG interface file instead.\n"); Printf(f, " * ----------------------------------------------------------------------------- */\n\n"); } /* ---------------------------------------------------------------------- * nativeWrapper() * ---------------------------------------------------------------------- */ virtual int nativeWrapper(Node *n) { String *wrapname = Getattr(n,"wrap:name"); if (!addSymbol(wrapname,n)) return SWIG_ERROR; if (Getattr(n,"type")) { Swig_save("nativeWrapper",n,"name",NIL); Setattr(n,"name", wrapname); native_function_flag = true; functionWrapper(n); Swig_restore(n); native_function_flag = false; } else { Printf(stderr,"%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n,"wrap:name")); } return SWIG_OK; } /* ---------------------------------------------------------------------- * functionWrapper() * ---------------------------------------------------------------------- */ virtual int functionWrapper(Node *n) { String *symname = Getattr(n,"sym:name"); SwigType *t = Getattr(n,"type"); ParmList *l = Getattr(n,"parms"); String *tm; Parm *p; int i; String *c_return_type = NewString(""); String *im_return_type = NewString(""); String *cleanup = NewString(""); String *outarg = NewString(""); String *body = NewString(""); String *im_outattribute = 0; int num_arguments = 0; int num_required = 0; bool is_void_return; String *overloaded_name = getOverloadedName(n); if (!Getattr(n,"sym:overloaded")) { if (!addSymbol(Getattr(n,"sym:name"),n)) return SWIG_ERROR; } /* The rest of this function deals with generating the intermediary class wrapper function (that wraps a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a matching PInvoke c function call. */ // A new wrapper function object Wrapper *f = NewWrapper(); // Make a wrapper name for this function String *wname = Swig_name_wrapper(overloaded_name); /* Attach the non-standard typemaps to the parameter list. */ Swig_typemap_attach_parms("ctype", l, f); Swig_typemap_attach_parms("imtype", l, f); /* Get return types */ if ((tm = Swig_typemap_lookup_new("ctype",n,"",0))) { String *ctypeout = Getattr(n,"tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap if (ctypeout) tm = ctypeout; Printf(c_return_type,"%s", tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t,0)); } if ((tm = Swig_typemap_lookup_new("imtype",n,"",0))) { String *imtypeout = Getattr(n,"tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap if (imtypeout) tm = imtypeout; Printf(im_return_type,"%s", tm); im_outattribute = Getattr(n,"tmap:imtype:outattributes"); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t,0)); } is_void_return = (Cmp(c_return_type, "void") == 0); if (!is_void_return) Wrapper_add_localv(f,"jresult", c_return_type, "jresult",NIL); Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL); // Emit all of the local variables for holding arguments. emit_args(t,l,f); /* Attach the standard typemaps */ emit_attach_parmmaps(l,f); // Parameter overloading Setattr(n,"wrap:parms",l); Setattr(n,"wrap:name", wname); // Wrappers not wanted for some methods where the parameters cannot be overloaded in C# if (Getattr(n,"sym:overloaded")) { // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper Swig_overload_check(n); if (Getattr(n, "overload:ignore")) return SWIG_OK; } Printv(imclass_class_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", overloaded_name, "\")]\n", NIL); if (im_outattribute) Printf(imclass_class_code, " %s\n", im_outattribute); Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name); /* Get number of required and total arguments */ num_arguments = emit_num_arguments(l); num_required = emit_num_required(l); int gencomma = 0; // Now walk the function parameter list and generate code to get arguments for (i = 0, p=l; i < num_arguments; i++) { while (checkAttribute(p,"tmap:in:numinputs","0")) { p = Getattr(p,"tmap:in:next"); } SwigType *pt = Getattr(p,"type"); String *ln = Getattr(p,"lname"); String *im_param_type = NewString(""); String *c_param_type = NewString(""); String *arg = NewString(""); Printf(arg,"j%s", ln); /* Get the ctype types of the parameter */ if ((tm = Getattr(p,"tmap:ctype"))) { Printv(c_param_type, tm, NIL); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt,0)); } /* Get the intermediary class parameter types of the parameter */ if ((tm = Getattr(p,"tmap:imtype"))) { String *inattributes = Getattr(p,"tmap:imtype:inattributes"); Printf(im_param_type, "%s%s", inattributes ? (const String *)inattributes : empty_string, tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt,0)); } /* Add parameter to intermediary class method */ if(gencomma) Printf(imclass_class_code, ", "); Printf(imclass_class_code, "%s %s", im_param_type, arg); // Add parameter to C function Printv(f->def, gencomma?", ":"", c_param_type, " ", arg, NIL); gencomma = 1; // Get typemap for this argument if ((tm = Getattr(p,"tmap:in"))) { canThrow(n, "in", p); Replaceall(tm,"$source",arg); /* deprecated */ Replaceall(tm,"$target",ln); /* deprecated */ Replaceall(tm,"$arg",arg); /* deprecated? */ Replaceall(tm,"$input", arg); Setattr(p,"emit:input", arg); Printf(f->code,"%s\n", tm); p = Getattr(p,"tmap:in:next"); } else { Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n",SwigType_str(pt,0)); p = nextSibling(p); } Delete(im_param_type); Delete(c_param_type); Delete(arg); } /* Insert constraint checking code */ for (p = l; p;) { if ((tm = Getattr(p,"tmap:check"))) { canThrow(n, "check", p); Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */ Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */ Replaceall(tm,"$input",Getattr(p,"emit:input")); Printv(f->code,tm,"\n",NIL); p = Getattr(p,"tmap:check:next"); } else { p = nextSibling(p); } } /* Insert cleanup code */ for (p = l; p;) { if ((tm = Getattr(p,"tmap:freearg"))) { canThrow(n, "freearg", p); Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */ Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */ Replaceall(tm,"$input",Getattr(p,"emit:input")); Printv(cleanup,tm,"\n",NIL); p = Getattr(p,"tmap:freearg:next"); } else { p = nextSibling(p); } } /* Insert argument output code */ for (p = l; p;) { if ((tm = Getattr(p,"tmap:argout"))) { canThrow(n, "argout", p); Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */ Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */ Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */ Replaceall(tm,"$result","jresult"); Replaceall(tm,"$input",Getattr(p,"emit:input")); Printv(outarg,tm,"\n",NIL); p = Getattr(p,"tmap:argout:next"); } else { p = nextSibling(p); } } // Get any C# exception classes in the throws typemap ParmList *throw_parm_list = NULL; if ((throw_parm_list = Getattr(n,"throws"))) { Swig_typemap_attach_parms("throws", throw_parm_list, f); for (p = throw_parm_list; p; p=nextSibling(p)) { if ((tm = Getattr(p,"tmap:throws"))) { canThrow(n, "throws", p); } } } if (Cmp(nodeType(n), "constant") == 0) { // Wrapping a constant hack Swig_save("functionWrapper",n,"wrap:action",NIL); // below based on Swig_VargetToFunction() SwigType *ty = Swig_wrapped_var_type(Getattr(n,"type")); Setattr(n,"wrap:action", NewStringf("result = (%s) %s;\n", SwigType_lstr(ty,0), Getattr(n, "value"))); } // Now write code to make the function call if(!native_function_flag) emit_action(n,f); if (Cmp(nodeType(n), "constant") == 0) Swig_restore(n); /* Return value if necessary */ String *null_attribute = 0; if(!native_function_flag) { if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) { canThrow(n, "out", n); Replaceall(tm,"$source", "result"); /* deprecated */ Replaceall(tm,"$target", "jresult"); /* deprecated */ Replaceall(tm,"$result","jresult"); Printf(f->code,"%s", tm); null_attribute = Getattr(n, "tmap:out:null"); if (Len(tm)) Printf(f->code,"\n"); } else { Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t,0), Getattr(n,"name")); } } /* Output argument output code */ Printv(f->code,outarg,NIL); /* Output cleanup code */ Printv(f->code,cleanup,NIL); /* Look to see if there is any newfree cleanup code */ if (GetFlag(n,"feature:new")) { if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) { canThrow(n, "newfree", n); Replaceall(tm,"$source","result"); /* deprecated */ Printf(f->code,"%s\n",tm); } } /* See if there is any return cleanup code */ if(!native_function_flag) { if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) { canThrow(n, "ret", n); Replaceall(tm,"$source","result"); /* deprecated */ Printf(f->code,"%s\n",tm); } } /* Finish C function and intermediary class function definitions */ Printf(imclass_class_code, ")"); Printf(imclass_class_code, ";\n"); Printf(f->def,") {"); if(!is_void_return) Printv(f->code, " return jresult;\n", NIL); Printf(f->code, "}\n"); /* Substitute the cleanup code */ Replaceall(f->code,"$cleanup",cleanup); /* Contract macro modification */ if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) { Setattr(n,"csharp:canthrow","1"); } if(!null_attribute) Replaceall(f->code,"$null","0"); else Replaceall(f->code,"$null",null_attribute); /* Dump the function out */ if(!native_function_flag) { Wrapper_print(f,f_wrappers); // Handle %csexception which sets the canthrow attribute if (Getattr(n,"feature:except:canthrow")) Setattr(n,"csharp:canthrow","1"); // A very simple check (it is not foolproof) to help typemap/feature writers for // throwing C# exceptions from unmanaged code. It checks for the common methods which // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set // so that code which checks for pending exceptions is added in the C# proxy method. if (!Getattr(n,"csharp:canthrow")) { if(Strstr(f->code, "SWIG_exception")) { Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number, "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n"); } else if(Strstr(f->code, "SWIG_CSharpSetPendingException")) { Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number, "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n"); } } } if(!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) { moduleClassFunctionHandler(n); } /* * Generate the proxy class properties for public member variables. * Not for enums and constants. */ if(proxy_flag && wrapping_member_flag && !enum_constant_flag) { // Capitalize the first letter in the variable in the getter/setter function name bool getter_flag = Cmp(symname, Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) != 0; String *getter_setter_name = NewString(""); if(!getter_flag) Printf(getter_setter_name,"set"); else Printf(getter_setter_name,"get"); Putc(toupper((int) *Char(variable_name)), getter_setter_name); Printf(getter_setter_name, "%s", Char(variable_name)+1); Setattr(n,"proxyfuncname", getter_setter_name); Setattr(n,"imfuncname", symname); proxyClassFunctionHandler(n); Delete(getter_setter_name); } Delete(c_return_type); Delete(im_return_type); Delete(cleanup); Delete(outarg); Delete(body); Delete(overloaded_name); DelWrapper(f); return SWIG_OK; } /* ----------------------------------------------------------------------- * variableWrapper() * ----------------------------------------------------------------------- */ virtual int variableWrapper(Node *n) { Language::variableWrapper(n); return SWIG_OK; } /* ----------------------------------------------------------------------- * globalvariableHandler() * ------------------------------------------------------------------------ */ virtual int globalvariableHandler(Node *n) { generate_property_declaration_flag = true; variable_name = Getattr(n,"sym:name"); global_variable_flag = true; int ret = Language::globalvariableHandler(n); global_variable_flag = false; generate_property_declaration_flag = false; Printf(module_class_code, "\n }\n\n"); return ret; } /* ---------------------------------------------------------------------- * enumDeclaration() * * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified: * 1) Simple enums - simple constant within the proxy class or module class * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name) * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name) * 4) Proper enums - proper C# enum * Anonymous enums always default to 1) * ---------------------------------------------------------------------- */ virtual int enumDeclaration(Node *n) { if (!ImportMode) { if (getCurrentClass() && (cplus_mode != PUBLIC)) return SWIG_NOWRAP; enum_code = NewString(""); String *symname = Getattr(n,"sym:name"); String *constants_code = (proxy_flag && is_wrapping_class()) ? proxy_class_constants_code : module_class_constants_code; EnumFeature enum_feature = decodeEnumFeature(n); String *typemap_lookup_type = Getattr(n,"name"); if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) { // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum // Pure C# baseclass and interfaces const String *pure_baseclass = typemapLookup("csbase", typemap_lookup_type, WARN_NONE); const String *pure_interfaces = typemapLookup("csinterfaces", typemap_lookup_type, WARN_NONE); // Class attributes const String *csattributes = typemapLookup("csattributes", typemap_lookup_type, WARN_NONE); if (csattributes && *Char(csattributes)) Printf(enum_code, "%s\n", csattributes); // Emit the enum Printv(enum_code, typemapLookup("csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really) " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces ", " : "", pure_interfaces, " {\n", NIL); } else { // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort if (symname && !Getattr(n,"unnamedinstance")) Printf(constants_code, " // %s \n", symname); } // Emit each enum item Language::enumDeclaration(n); if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) { // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum // Finish the enum declaration // Typemaps are used to generate the enum definition in a similar manner to proxy classes. Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup("csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class typemapLookup("cscode", typemap_lookup_type, WARN_NONE), // extra C# code "}", NIL); Replaceall(enum_code, "$csclassname", symname); // Substitute $enumvalues - intended usage is for typesafe enums if (Getattr(n,"enumvalues")) Replaceall(enum_code, "$enumvalues", Getattr(n,"enumvalues")); else Replaceall(enum_code, "$enumvalues", ""); if (proxy_flag && is_wrapping_class()) { // Enums defined within the C++ class are defined within the proxy class // Add extra indentation Replaceall(enum_code, "\n", "\n "); Replaceall(enum_code, " \n", "\n"); Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL); } else { // Global enums are defined in their own file String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), symname); File *f_enum = NewFile(filen,"w"); if(!f_enum) { FileErrorDisplay(filen); SWIG_exit(EXIT_FAILURE); } Append(filenames_list, Copy(filen)); Delete(filen); filen = NULL; // Start writing out the enum file emitBanner(f_enum); if(Len(namespce) > 0) Printf(f_enum, "namespace %s {\n", namespce); Printv(f_enum, typemapLookup("csimports", typemap_lookup_type, WARN_NONE), // Import statements "\n", enum_code, "\n", NIL); Printf(f_enum, Len(namespce) > 0 ? "\n}\n" : ""); Close(f_enum); } } else { // Wrap C++ enum with simple constant Printf(enum_code, "\n"); if (proxy_flag && is_wrapping_class()) Printv(proxy_class_constants_code, enum_code, NIL); else Printv(module_class_constants_code, enum_code, NIL); } Delete(enum_code); enum_code = NULL; } return SWIG_OK; } /* ---------------------------------------------------------------------- * enumvalueDeclaration() * ---------------------------------------------------------------------- */ virtual int enumvalueDeclaration(Node *n) { if (getCurrentClass() && (cplus_mode != PUBLIC)) return SWIG_NOWRAP; Swig_require("enumvalueDeclaration",n,"*name", "?value",NIL); String *symname = Getattr(n,"sym:name"); String *value = Getattr(n,"value"); String *name = Getattr(n,"name"); String *tmpValue; // Strange hack from parent method if (value) tmpValue = NewString(value); else tmpValue = NewString(name); // Note that this is used in enumValue() amongst other places Setattr(n, "value", tmpValue); { EnumFeature enum_feature = decodeEnumFeature(parentNode(n)); if ((enum_feature == ProperEnum) && Getattr(parentNode(n),"sym:name") && !Getattr(parentNode(n),"unnamedinstance")) { // Wrap (non-anonymous) C/C++ enum with a proper C# enum // Emit the enum item. if (!Getattr(n,"_last")) // Only the first enum item has this attribute set Printf(enum_code, ",\n"); Printf(enum_code, " %s", symname); // Check for the %csconstvalue feature String *value = Getattr(n,"feature:cs:constvalue"); // Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0) value = value ? value : Getattr(n,"enumvalue"); if (value) { Printf(enum_code, " = %s", value); } } else { // Wrap C/C++ enums with constant integers or use the typesafe enum pattern const String *parent_name = Getattr(parentNode(n),"name"); String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int"); const String *tm = typemapLookup("cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF); String *return_type = Copy(tm); Delete(typemap_lookup_type); typemap_lookup_type = NULL; // The %csconst feature determines how the constant value is obtained int const_feature_flag = GetFlag(n,"feature:cs:const"); if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n),"sym:name") && !Getattr(parentNode(n),"unnamedinstance")) { // Wrap (non-anonymouse) enum using the typesafe enum pattern if (Getattr(n,"enumvalue")) { String *value = enumValue(n); Printf(enum_code, " public static readonly %s %s = new %s(\"%s\", %s);\n", return_type, symname, return_type, symname, value); Delete(value); } else { Printf(enum_code, " public static readonly %s %s = new %s(\"%s\");\n", return_type, symname, return_type, symname); } } else { // Simple integer constants // Note these are always generated for anonymous enums, no matter what enum_feature is specified // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later const char *const_readonly = const_feature_flag ? "const" : "static readonly"; String *value = enumValue(n); Printf(enum_code, " public %s %s %s = %s;\n", const_readonly, return_type, symname, value); Delete(value); } } // Add the enum value to the comma separated list being constructed in the enum declaration. String *enumvalues = Getattr(parentNode(n), "enumvalues"); if (!enumvalues) Setattr(parentNode(n), "enumvalues", Copy(symname)); else Printv(enumvalues, ", ", symname, NIL); } Delete(tmpValue); Swig_restore(n); return SWIG_OK; } /* ----------------------------------------------------------------------- * constantWrapper() * Used for wrapping constants - #define or %constant. * Also for inline initialised const static primitive type member variables (short, int, double, enums etc). * C# static const variables are generated for these. * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable. * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable. * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation. * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)). * ------------------------------------------------------------------------ */ virtual int constantWrapper(Node *n) { String *symname = Getattr(n,"sym:name"); SwigType *t = Getattr(n,"type"); ParmList *l = Getattr(n,"parms"); String *tm; String *return_type = NewString(""); String *constants_code = NewString(""); if (!addSymbol(symname,n)) return SWIG_ERROR; bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0); // The %csconst feature determines how the constant value is obtained int const_feature_flag = GetFlag(n,"feature:cs:const"); /* Adjust the enum type for the Swig_typemap_lookup. * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */ if (is_enum_item) { t = Getattr(parentNode(n),"enumtype"); Setattr(n,"type", t); } /* Attach the non-standard typemaps to the parameter list. */ Swig_typemap_attach_parms("cstype", l, NULL); /* Get C# return types */ bool classname_substituted_flag = false; if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) { String *cstypeout = Getattr(n,"tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap if (cstypeout) tm = cstypeout; classname_substituted_flag = substituteClassname(t, tm); Printf(return_type, "%s", tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t,0)); } // Add the stripped quotes back in String *new_value = NewString(""); Swig_save("constantWrapper",n,"value",NIL); if(SwigType_type(t) == T_STRING) { Printf(new_value, "\"%s\"", Copy(Getattr(n, "value"))); Setattr(n, "value", new_value); } else if(SwigType_type(t) == T_CHAR) { Printf(new_value, "\'%s\'", Copy(Getattr(n, "value"))); Setattr(n, "value", new_value); } const String *outattributes = Getattr(n,"tmap:cstype:outattributes"); if (outattributes) Printf(constants_code, " %s\n", outattributes); const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; Printf(constants_code, " public %s %s %s = ", (const_feature_flag ? "const" : "static readonly"), return_type, itemname); // Check for the %csconstvalue feature String *value = Getattr(n,"feature:cs:constvalue"); if (value) { Printf(constants_code, "%s;\n", value); } else if (!const_feature_flag) { // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call. if(classname_substituted_flag) { if (SwigType_isenum(t)) { // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on) Printf(constants_code, "(%s)%s.%s();\n", return_type, imclass_name, Swig_name_get(symname)); } else { // This handles function pointers using the %constant directive Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname)); } } else Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname)); // Each constant and enum value is wrapped with a separate PInvoke function call SetFlag(n,"feature:immutable"); enum_constant_flag = true; variableWrapper(n); enum_constant_flag = false; } else { // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code Printf(constants_code, "%s;\n", Getattr(n,"value")); } // Emit the generated code to appropriate place // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed if (!is_enum_item) { if(proxy_flag && wrapping_member_flag) Printv(proxy_class_constants_code, constants_code, NIL); else Printv(module_class_constants_code, constants_code, NIL); } // Cleanup Swig_restore(n); Delete(new_value); Delete(return_type); Delete(constants_code); return SWIG_OK; } /* ----------------------------------------------------------------------------- * insertDirective() * ----------------------------------------------------------------------------- */ virtual int insertDirective(Node *n) { String *code = Getattr(n,"code"); Replaceall(code, "$module", module_class_name); Replaceall(code, "$imclassname", imclass_name); Replaceall(code, "$dllimport", dllimport); return Language::insertDirective(n); } /* ----------------------------------------------------------------------------- * pragmaDirective() * * Valid Pragmas: * imclassbase - base (extends) for the intermediary class * imclassclassmodifiers - class modifiers for the intermediary class * imclasscode - text (C# code) is copied verbatim to the intermediary class * imclassimports - import statements for the intermediary class * imclassinterfaces - interface (implements) for the intermediary class * * modulebase - base (extends) for the module class * moduleclassmodifiers - class modifiers for the module class * modulecode - text (C# code) is copied verbatim to the module class * moduleimports - import statements for the module class * moduleinterfaces - interface (implements) for the module class * * ----------------------------------------------------------------------------- */ virtual int pragmaDirective(Node *n) { if (!ImportMode) { String *lang = Getattr(n,"lang"); String *code = Getattr(n,"name"); String *value = Getattr(n,"value"); if(Strcmp(lang, "csharp") == 0) { String *strvalue = NewString(value); Replaceall(strvalue,"\\\"", "\""); if(Strcmp(code, "imclassbase") == 0) { Delete(imclass_baseclass); imclass_baseclass = Copy(strvalue); } else if(Strcmp(code, "imclassclassmodifiers") == 0) { Delete(imclass_class_modifiers); imclass_class_modifiers = Copy(strvalue); } else if(Strcmp(code, "imclasscode") == 0) { Printf(imclass_class_code, "%s\n", strvalue); } else if(Strcmp(code, "imclassimports") == 0) { Delete(imclass_imports); imclass_imports = Copy(strvalue); } else if(Strcmp(code, "imclassinterfaces") == 0) { Delete(imclass_interfaces); imclass_interfaces = Copy(strvalue); } else if(Strcmp(code, "modulebase") == 0) { Delete(module_baseclass); module_baseclass = Copy(strvalue); } else if(Strcmp(code, "moduleclassmodifiers") == 0) { Delete(module_class_modifiers); module_class_modifiers = Copy(strvalue); } else if(Strcmp(code, "modulecode") == 0) { Printf(module_class_code, "%s\n", strvalue); } else if(Strcmp(code, "moduleimports") == 0) { Delete(module_imports); module_imports = Copy(strvalue); } else if(Strcmp(code, "moduleinterfaces") == 0) { Delete(module_interfaces); module_interfaces = Copy(strvalue); } else { Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file, line_number); } Delete(strvalue); } } return Language::pragmaDirective(n); } /* ----------------------------------------------------------------------------- * emitProxyClassDefAndCPPCasts() * ----------------------------------------------------------------------------- */ void emitProxyClassDefAndCPPCasts(Node *n) { String *c_classname = SwigType_namestr(Getattr(n,"name")); String *c_baseclass = NULL; String *baseclass = NULL; String *c_baseclassname = NULL; String *typemap_lookup_type = Getattr(n,"classtypeobj"); /* Deal with inheritance */ List *baselist = Getattr(n,"bases"); if (baselist) { Iterator base = First(baselist); while(base.item && GetFlag(base.item,"feature:ignore")) { base = Next(base); } if (base.item) { c_baseclassname = Getattr(base.item,"name"); baseclass = Copy(getProxyName(c_baseclassname)); if (baseclass) c_baseclass = SwigType_namestr(Getattr(base.item,"name")); base = Next(base); /* Warn about multiple inheritance for additional base class(es) */ while (base.item) { if (GetFlag(base.item,"feature:ignore")) { base = Next(base); continue; } String *proxyclassname = SwigType_str(Getattr(n,"classtypeobj"),0); String *baseclassname = SwigType_str(Getattr(base.item,"name"),0); Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number, "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", proxyclassname, baseclassname); base = Next(base); } } } bool derived = baseclass && getProxyName(c_baseclassname); if (!baseclass) baseclass = NewString(""); // Inheritance from pure C# classes const String *pure_baseclass = typemapLookup("csbase", typemap_lookup_type, WARN_NONE); if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) { Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number, "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", typemap_lookup_type, pure_baseclass); pure_baseclass = empty_string; } // Pure C# interfaces const String *pure_interfaces = typemapLookup(derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE); // Start writing the proxy class Printv(proxy_class_def, typemapLookup("csimports", typemap_lookup_type, WARN_NONE), // Import statements "\n", NIL); // Class attributes const String *csattributes = typemapLookup("csattributes", typemap_lookup_type, WARN_NONE); if (csattributes && *Char(csattributes)) Printf(proxy_class_def, "%s\n", csattributes); Printv(proxy_class_def, typemapLookup("csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " $csclassname", // Class name and base class (derived || *Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", baseclass, // Note only one of these base classes should ever be set as multiple inheritance is not permissible pure_baseclass, ((derived || *Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces ", " : "", pure_interfaces, " {", derived ? typemapLookup("csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class typemapLookup("csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class NIL); // C++ destructor is wrapped by the Dispose method // Note that the method name is specified in a typemap attribute called methodname String *destruct = NewString(""); const String *tm = NULL; Node *attributes = NewHash(); String *destruct_methodname = NULL; if (derived) { tm = typemapLookup("csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname"); } else { tm = typemapLookup("csdestruct", typemap_lookup_type, WARN_NONE, attributes); destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname"); } if (!destruct_methodname) { Swig_error(input_file, line_number, "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name); } // Emit the Finalize and Dispose methods if (tm) { // Finalize method if (*Char(destructor_call)) { Printv(proxy_class_def, typemapLookup("csfinalize", typemap_lookup_type, WARN_NONE), NIL); } // Dispose method Printv(destruct, tm, NIL); if (*Char(destructor_call)) Replaceall(destruct, "$imcall", destructor_call); else Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")"); if (*Char(destruct)) Printv(proxy_class_def, "\n public ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n", NIL); } Delete(attributes); Delete(destruct); // Emit extra user code Printv(proxy_class_def, typemapLookup("cscode", typemap_lookup_type, WARN_NONE), // extra C# code "\n", NIL); // Substitute various strings into the above template Replaceall(proxy_class_code, "$csclassname", proxy_class_name); Replaceall(proxy_class_def, "$csclassname", proxy_class_name); Replaceall(proxy_class_def, "$module", module_class_name); Replaceall(proxy_class_code, "$module", module_class_name); Replaceall(proxy_class_def, "$imclassname", imclass_name); Replaceall(proxy_class_code, "$imclassname", imclass_name); Replaceall(proxy_class_def, "$dllimport", dllimport); Replaceall(proxy_class_code, "$dllimport", dllimport); // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy) if(derived){ Printv(imclass_cppcasts_code,"\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", proxy_class_name ,"Upcast", "\")]\n", NIL); Printf(imclass_cppcasts_code," public static extern IntPtr $csclassnameUpcast(IntPtr objectRef);\n"); Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); Printv(upcasts_code, "SWIGEXPORT $cbaseclass * SWIGSTDCALL CSharp_$imclazznameUpcast", "($cclass *objectRef) {\n", " return ($cbaseclass *)objectRef;\n" "}\n", "\n", NIL); Replaceall(upcasts_code, "$cbaseclass", c_baseclass); Replaceall(upcasts_code, "$imclazzname", proxy_class_name); Replaceall(upcasts_code, "$cclass", c_classname); } Delete(baseclass); } /* ---------------------------------------------------------------------- * classHandler() * ---------------------------------------------------------------------- */ virtual int classHandler(Node *n) { File *f_proxy = NULL; if (proxy_flag) { proxy_class_name = NewString(Getattr(n,"sym:name")); if (!addSymbol(proxy_class_name,n)) return SWIG_ERROR; if (Cmp(proxy_class_name, imclass_name) == 0) { Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name); SWIG_exit(EXIT_FAILURE); } if (Cmp(proxy_class_name, module_class_name) == 0) { Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name); SWIG_exit(EXIT_FAILURE); } String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), proxy_class_name); f_proxy = NewFile(filen,"w"); if(!f_proxy) { FileErrorDisplay(filen); SWIG_exit(EXIT_FAILURE); } Append(filenames_list, Copy(filen)); Delete(filen); filen = NULL; // Start writing out the proxy class file emitBanner(f_proxy); if(Len(namespce) > 0) Printf(f_proxy, "namespace %s {\n", namespce); Clear(proxy_class_def); Clear(proxy_class_code); destructor_call = NewString(""); proxy_class_constants_code = NewString(""); } Language::classHandler(n); if (proxy_flag) { emitProxyClassDefAndCPPCasts(n); Replaceall(proxy_class_def, "$module", module_class_name); Replaceall(proxy_class_code, "$module", module_class_name); Replaceall(proxy_class_constants_code, "$module", module_class_name); Replaceall(proxy_class_def, "$imclassname", imclass_name); Replaceall(proxy_class_code, "$imclassname", imclass_name); Replaceall(proxy_class_constants_code, "$imclassname", imclass_name); Replaceall(proxy_class_def, "$dllimport", dllimport); Replaceall(proxy_class_code, "$dllimport", dllimport); Replaceall(proxy_class_constants_code, "$dllimport", dllimport); Printv(f_proxy, proxy_class_def, proxy_class_code, NIL); // Write out all the constants if (Len(proxy_class_constants_code) != 0 ) Printv(f_proxy, proxy_class_constants_code, NIL); Printf(f_proxy, "}\n"); Printf(f_proxy, Len(namespce) > 0 ? "\n}\n" : ""); Close(f_proxy); f_proxy = NULL; Delete(proxy_class_name); proxy_class_name = NULL; Delete(destructor_call); destructor_call = NULL; Delete(proxy_class_constants_code); proxy_class_constants_code = NULL; } return SWIG_OK; } /* ---------------------------------------------------------------------- * memberfunctionHandler() * ---------------------------------------------------------------------- */ virtual int memberfunctionHandler(Node *n) { Language::memberfunctionHandler(n); if (proxy_flag) { String *overloaded_name = getOverloadedName(n); String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name); Setattr(n,"proxyfuncname", Getattr(n, "sym:name")); Setattr(n,"imfuncname", intermediary_function_name); proxyClassFunctionHandler(n); Delete(overloaded_name); } return SWIG_OK; } /* ---------------------------------------------------------------------- * staticmemberfunctionHandler() * ---------------------------------------------------------------------- */ virtual int staticmemberfunctionHandler(Node *n) { static_flag = true; Language::staticmemberfunctionHandler(n); if (proxy_flag) { String *overloaded_name = getOverloadedName(n); String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name); Setattr(n,"proxyfuncname", Getattr(n,"sym:name")); Setattr(n,"imfuncname", intermediary_function_name); proxyClassFunctionHandler(n); Delete(overloaded_name); } static_flag = false; return SWIG_OK; } /* ----------------------------------------------------------------------------- * proxyClassFunctionHandler() * * Function called for creating a C# wrapper function around a c++ function in the * proxy class. Used for both static and non-static C++ class functions. * C++ class static functions map to C# static functions. * Two extra attributes in the Node must be available. These are "proxyfuncname" - * the name of the C# class proxy function, which in turn will call "imfuncname" - * the intermediary (PInvoke) function name in the intermediary class. * ----------------------------------------------------------------------------- */ void proxyClassFunctionHandler(Node *n) { SwigType *t = Getattr(n,"type"); ParmList *l = Getattr(n,"parms"); String *intermediary_function_name = Getattr(n,"imfuncname"); String *proxy_function_name = Getattr(n,"proxyfuncname"); String *tm; Parm *p; Parm *last_parm = 0; int i; String *imcall = NewString(""); String *return_type = NewString(""); String *function_code = NewString(""); bool setter_flag = false; if(!proxy_flag) return; // Wrappers not wanted for some methods where the parameters cannot be overloaded in C# if (Getattr(n, "overload:ignore")) return; if (l) { if (SwigType_type(Getattr(l,"type")) == T_VOID) { l = nextSibling(l); } } /* Attach the non-standard typemaps to the parameter list */ Swig_typemap_attach_parms("in", l, NULL); Swig_typemap_attach_parms("cstype", l, NULL); Swig_typemap_attach_parms("csin", l, NULL); /* Get return types */ if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) { // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type SwigType *covariant = Getattr(n,"covariant"); String *cstypeout = Getattr(n,"tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap if (cstypeout) tm = cstypeout; substituteClassname(covariant ? covariant : t, tm); Printf(return_type, "%s", tm); if (covariant) Swig_warning(WARN_CSHARP_COVARIANT_RET, input_file, line_number, "Covariant return types not supported in C#. Proxy method will return %s.\n", SwigType_str(covariant,0)); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t,0)); } if(proxy_flag && wrapping_member_flag && !enum_constant_flag) { // Properties setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0); } /* Start generating the proxy function */ const String *outattributes = Getattr(n,"tmap:cstype:outattributes"); if (outattributes) Printf(function_code, " %s\n", outattributes); const String *csattributes = Getattr(n,"feature:cs:attributes"); if (csattributes) Printf(function_code, " %s\n", csattributes); const String *methodmods = Getattr(n,"feature:cs:methodmodifiers"); if (methodmods) { Printf(function_code, " %s ", methodmods); } else { methodmods = (!is_public(n) ? protected_string : public_string); Printf(function_code, " %s ", methodmods); if (Getattr(n,"override")) Printf(function_code, "override "); else if (checkAttribute(n, "storage", "virtual")) Printf(function_code, "virtual "); if (Getattr(n, "hides")) Printf(function_code, "new "); } if (static_flag) Printf(function_code, "static "); Printf(function_code, "%s %s(", return_type, proxy_function_name); Printv(imcall, imclass_name, ".", intermediary_function_name, "(", NIL); if (!static_flag) Printf(imcall, "swigCPtr"); emit_mark_varargs(l); int gencomma = !static_flag; /* Output each parameter */ for (i = 0, p=l; p; i++) { /* Ignored varargs */ if (checkAttribute(p,"varargs:ignore","1")) { p = nextSibling(p); continue; } /* Ignored parameters */ if (checkAttribute(p,"tmap:in:numinputs","0")) { p = Getattr(p,"tmap:in:next"); continue; } /* Ignore the 'this' argument for variable wrappers */ if (!(variable_wrapper_flag && i==0)) { SwigType *pt = Getattr(p,"type"); String *param_type = NewString(""); last_parm = p; /* Get the C# parameter type */ if ((tm = Getattr(p,"tmap:cstype"))) { substituteClassname(pt, tm); String *inattributes = Getattr(p,"tmap:cstype:inattributes"); Printf(param_type, "%s%s", inattributes ? (const String *)inattributes : empty_string, tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt,0)); } if (gencomma) Printf(imcall, ", "); String *arg = makeParameterName(n, p, i, setter_flag); // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class) if ((tm = Getattr(p,"tmap:csin"))) { substituteClassname(pt, tm); Replaceall(tm, "$csinput", arg); Printv(imcall, tm, NIL); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt,0)); } /* Add parameter to proxy function */ if (gencomma >= 2) Printf(function_code, ", "); gencomma = 2; Printf(function_code, "%s %s", param_type, arg); Delete(arg); Delete(param_type); } p = Getattr(p,"tmap:in:next"); } Printf(imcall, ")"); Printf(function_code, ")"); // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class) if ((tm = Swig_typemap_lookup_new("csout",n,"",0))) { if (GetFlag(n,"feature:new")) Replaceall(tm,"$owner","true"); else Replaceall(tm,"$owner","false"); substituteClassname(t, tm); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csout", n); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t,0)); } if(proxy_flag && wrapping_member_flag && !enum_constant_flag) { // Properties if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get // Get the C# variable type - obtained differently depending on whether a setter is required. String *variable_type = return_type; if (setter_flag) { p = last_parm; // (last parameter is the only parameter for properties) SwigType *pt = Getattr(p,"type"); if ((tm = Getattr(p,"tmap:cstype"))) { substituteClassname(pt, tm); variable_type = tm; } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt,0)); } } const String *csattributes = Getattr(n,"feature:cs:attributes"); if (csattributes) Printf(proxy_class_code, " %s\n", csattributes); const String *methodmods = Getattr(n,"feature:cs:methodmodifiers"); if (!methodmods) methodmods = (!is_public(n) ? protected_string : public_string); Printf(proxy_class_code, " %s %s%s %s {", methodmods, static_flag ? "static " : "", variable_type, variable_name); } generate_property_declaration_flag = false; if(setter_flag) { // Setter method Swig_typemap_attach_parms("csvarin", l, NULL); p = last_parm; // (last parameter is the only parameter for properties) SwigType *pt = Getattr(p,"type"); if ((tm = Getattr(p,"tmap:csvarin"))) { substituteClassname(pt, tm); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarin", p); Printf(proxy_class_code, "%s", tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt,0)); } } else { // Getter method if ((tm = Swig_typemap_lookup_new("csvarout",n,"",0))) { if (GetFlag(n,"feature:new")) Replaceall(tm,"$owner","true"); else Replaceall(tm,"$owner","false"); substituteClassname(t, tm); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarout", n); Printf(proxy_class_code, "%s", tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t,0)); } } } else { // Normal function call Printf(function_code, " %s\n\n", tm ? (const String *)tm : empty_string); Printv(proxy_class_code, function_code, NIL); } Delete(function_code); Delete(return_type); Delete(imcall); } /* ---------------------------------------------------------------------- * constructorHandler() * ---------------------------------------------------------------------- */ virtual int constructorHandler(Node *n) { ParmList *l = Getattr(n,"parms"); String *tm; Parm *p; int i; String *function_code = NewString(""); Language::constructorHandler(n); // Wrappers not wanted for some methods where the parameters cannot be overloaded in C# if (Getattr(n, "overload:ignore")) return SWIG_OK; if(proxy_flag) { String *overloaded_name = getOverloadedName(n); String *mangled_overname = Swig_name_construct(overloaded_name); String *imcall = NewString(""); const String *csattributes = Getattr(n,"feature:cs:attributes"); if (csattributes) Printf(function_code, " %s\n", csattributes); const String *methodmods = Getattr(n,"feature:cs:methodmodifiers"); methodmods = methodmods ? methodmods : (!is_public(n) ? protected_string : public_string); Printf(function_code, " %s %s(", methodmods, proxy_class_name); Printv(imcall, imclass_name, ".", mangled_overname, "(", NIL); /* Attach the non-standard typemaps to the parameter list */ Swig_typemap_attach_parms("in", l, NULL); Swig_typemap_attach_parms("cstype", l, NULL); Swig_typemap_attach_parms("csin", l, NULL); emit_mark_varargs(l); int gencomma = 0; /* Output each parameter */ for (i = 0, p=l; p; i++) { /* Ignored varargs */ if (checkAttribute(p,"varargs:ignore","1")) { p = nextSibling(p); continue; } /* Ignored parameters */ if (checkAttribute(p,"tmap:in:numinputs","0")) { p = Getattr(p,"tmap:in:next"); continue; } SwigType *pt = Getattr(p,"type"); String *param_type = NewString(""); /* Get the C# parameter type */ if ((tm = Getattr(p,"tmap:cstype"))) { substituteClassname(pt, tm); String *inattributes = Getattr(p,"tmap:cstype:inattributes"); Printf(param_type, "%s%s", inattributes ? (const String *)inattributes : empty_string, tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt,0)); } if (gencomma) Printf(imcall, ", "); String *arg = makeParameterName(n, p, i, false); // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class) if ((tm = Getattr(p,"tmap:csin"))) { substituteClassname(pt, tm); Replaceall(tm, "$csinput", arg); Printv(imcall, tm, NIL); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt,0)); } /* Add parameter to proxy function */ if(gencomma) Printf(function_code, ", "); Printf(function_code, "%s %s", param_type, arg); ++gencomma; Delete(arg); Delete(param_type); p = Getattr(p,"tmap:in:next"); } Printf(imcall, ")"); Printf(function_code, ")"); Node *attributes = NewHash(); Printv(function_code, " ", typemapLookup("csconstruct", Getattr(n,"name"), WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes), NIL); Replaceall(function_code, "$imcall", imcall); excodeSubstitute(n, function_code, "csconstruct", attributes); Printv(proxy_class_code, function_code, "\n", NIL); Delete(attributes); Delete(overloaded_name); Delete(imcall); } return SWIG_OK; } /* ---------------------------------------------------------------------- * destructorHandler() * ---------------------------------------------------------------------- */ virtual int destructorHandler(Node *n) { Language::destructorHandler(n); String *symname = Getattr(n,"sym:name"); if(proxy_flag) { Printv(destructor_call, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL); } return SWIG_OK; } /* ---------------------------------------------------------------------- * membervariableHandler() * ---------------------------------------------------------------------- */ virtual int membervariableHandler(Node *n) { generate_property_declaration_flag = true; variable_name = Getattr(n,"sym:name"); wrapping_member_flag = true; variable_wrapper_flag = true; Language::membervariableHandler(n); wrapping_member_flag = false; variable_wrapper_flag = false; generate_property_declaration_flag = false; Printf(proxy_class_code, "\n }\n\n"); return SWIG_OK; } /* ---------------------------------------------------------------------- * staticmembervariableHandler() * ---------------------------------------------------------------------- */ virtual int staticmembervariableHandler(Node *n) { bool static_const_member_flag = (Getattr(n, "value") == 0); generate_property_declaration_flag = true; variable_name = Getattr(n,"sym:name"); wrapping_member_flag = true; static_flag = true; Language::staticmembervariableHandler(n); wrapping_member_flag = false; static_flag = false; generate_property_declaration_flag = false; if(static_const_member_flag) Printf(proxy_class_code, "\n }\n\n"); return SWIG_OK; } /* ---------------------------------------------------------------------- * memberconstantHandler() * ---------------------------------------------------------------------- */ virtual int memberconstantHandler(Node *n) { variable_name = Getattr(n,"sym:name"); wrapping_member_flag = true; Language::memberconstantHandler(n); wrapping_member_flag = false; return SWIG_OK; } /* ----------------------------------------------------------------------------- * getOverloadedName() * ----------------------------------------------------------------------------- */ String *getOverloadedName(Node *n) { /* A C# HandleRef is used for all classes in the SWIG intermediary class. * The intermediary class methods are thus mangled when overloaded to give * a unique name. */ String *overloaded_name = NewStringf("%s", Getattr(n,"sym:name")); if (Getattr(n,"sym:overloaded")) { Printv(overloaded_name, Getattr(n,"sym:overname"), NIL); } return overloaded_name; } /* ----------------------------------------------------------------------------- * moduleClassFunctionHandler() * ----------------------------------------------------------------------------- */ void moduleClassFunctionHandler(Node *n) { SwigType *t = Getattr(n,"type"); ParmList *l = Getattr(n,"parms"); String *tm; Parm *p; Parm *last_parm = 0; int i; String *imcall = NewString(""); String *return_type = NewString(""); String *function_code = NewString(""); int num_arguments = 0; int num_required = 0; String *overloaded_name = getOverloadedName(n); String *func_name = NULL; bool setter_flag = false; if (l) { if (SwigType_type(Getattr(l,"type")) == T_VOID) { l = nextSibling(l); } } /* Attach the non-standard typemaps to the parameter list */ Swig_typemap_attach_parms("cstype", l, NULL); Swig_typemap_attach_parms("csin", l, NULL); /* Get return types */ if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) { String *cstypeout = Getattr(n,"tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap if (cstypeout) tm = cstypeout; substituteClassname(t, tm); Printf(return_type, "%s", tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t,0)); } /* Change function name for global variables */ if (proxy_flag && global_variable_flag) { // Capitalize the first letter in the variable to create the getter/setter function name func_name = NewString(""); setter_flag = (Cmp(Getattr(n,"sym:name"), Swig_name_set(variable_name)) == 0); if(setter_flag) Printf(func_name,"set"); else Printf(func_name,"get"); Putc(toupper((int) *Char(variable_name)), func_name); Printf(func_name, "%s", Char(variable_name)+1); } else { func_name = Copy(Getattr(n,"sym:name")); } /* Start generating the function */ const String *outattributes = Getattr(n,"tmap:cstype:outattributes"); if (outattributes) Printf(function_code, " %s\n", outattributes); const String *csattributes = Getattr(n,"feature:cs:attributes"); if (csattributes) Printf(function_code, " %s\n", csattributes); const String *methodmods = Getattr(n,"feature:cs:methodmodifiers"); methodmods = methodmods ? methodmods : (!is_public(n) ? protected_string : public_string); Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name); Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL); /* Get number of required and total arguments */ num_arguments = emit_num_arguments(l); num_required = emit_num_required(l); int gencomma = 0; /* Output each parameter */ for (i = 0, p=l; i < num_arguments; i++) { /* Ignored parameters */ while (checkAttribute(p,"tmap:in:numinputs","0")) { p = Getattr(p,"tmap:in:next"); } SwigType *pt = Getattr(p,"type"); String *param_type = NewString(""); last_parm = p; /* Get the C# parameter type */ if ((tm = Getattr(p,"tmap:cstype"))) { substituteClassname(pt, tm); String *inattributes = Getattr(p,"tmap:cstype:inattributes"); Printf(param_type, "%s%s", inattributes ? (const String *)inattributes : empty_string, tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt,0)); } if (gencomma) Printf(imcall, ", "); String *arg = makeParameterName(n, p, i, setter_flag); // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class) if ((tm = Getattr(p,"tmap:csin"))) { substituteClassname(pt, tm); Replaceall(tm, "$csinput", arg); Printv(imcall, tm, NIL); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt,0)); } /* Add parameter to module class function */ if (gencomma >= 2) Printf(function_code, ", "); gencomma = 2; Printf(function_code, "%s %s", param_type, arg); p = Getattr(p,"tmap:in:next"); Delete(arg); Delete(param_type); } Printf(imcall, ")"); Printf(function_code, ")"); // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in module class) if ((tm = Swig_typemap_lookup_new("csout",n,"",0))) { if (GetFlag(n,"feature:new")) Replaceall(tm,"$owner","true"); else Replaceall(tm,"$owner","false"); substituteClassname(t, tm); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csout", n); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t,0)); } if (proxy_flag && global_variable_flag) { // Properties if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get // Get the C# variable type - obtained differently depending on whether a setter is required. String *variable_type = return_type; if (setter_flag) { p = last_parm; // (last parameter is the only parameter for properties) SwigType *pt = Getattr(p,"type"); if ((tm = Getattr(p,"tmap:cstype"))) { substituteClassname(pt, tm); variable_type = tm; } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt,0)); } } const String *csattributes = Getattr(n,"feature:cs:attributes"); if (csattributes) Printf(module_class_code, " %s\n", csattributes); const String *methodmods = Getattr(n,"feature:cs:methodmodifiers"); if (!methodmods) methodmods = (!is_public(n) ? protected_string : public_string); Printf(module_class_code, " %s static %s %s {", methodmods, variable_type, variable_name); } generate_property_declaration_flag = false; if(setter_flag) { // Setter method Swig_typemap_attach_parms("csvarin", l, NULL); p = last_parm; // (last parameter is the only parameter for properties) SwigType *pt = Getattr(p,"type"); if ((tm = Getattr(p,"tmap:csvarin"))) { substituteClassname(pt, tm); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarin", p); Printf(module_class_code, "%s", tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt,0)); } } else { // Getter method if ((tm = Swig_typemap_lookup_new("csvarout",n,"",0))) { if (GetFlag(n,"feature:new")) Replaceall(tm,"$owner","true"); else Replaceall(tm,"$owner","false"); substituteClassname(t, tm); Replaceall(tm, "$imcall", imcall); excodeSubstitute(n, tm, "csvarout", n); Printf(module_class_code, "%s", tm); } else { Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t,0)); } } } else { // Normal function call Printf(function_code, " %s\n\n", tm ? (const String *)tm : empty_string); Printv(module_class_code, function_code, NIL); } Delete(function_code); Delete(return_type); Delete(imcall); Delete(func_name); } /*---------------------------------------------------------------------- * decodeEnumFeature() * Decode the possible enum features, which are one of: * %csenum(simple) * %csenum(typeunsafe) - default * %csenum(typesafe) * %csenum(proper) *--------------------------------------------------------------------*/ EnumFeature decodeEnumFeature(Node *n) { EnumFeature enum_feature = TypeunsafeEnum; String *feature = Getattr(n,"feature:cs:enum"); if (feature) { if (Cmp(feature, "simple") == 0) enum_feature = SimpleEnum; else if (Cmp(feature, "typesafe") == 0) enum_feature = TypesafeEnum; else if (Cmp(feature, "proper") == 0) enum_feature = ProperEnum; } return enum_feature; } /* ----------------------------------------------------------------------- * enumValue() * This method will return a string with an enum value to use in C# generated * code. If the %csconst feature is not used, the string will contain the intermediary * class call to obtain the enum value. The intermediary class and PINVOKE methods to obtain * the enum value will be generated. Otherwise the C/C++ enum value will be used if there * is one and hopefully it will compile as C# code - e.g. 20 as in: enum E{e=20}; * The %csconstvalue feature overrides all other ways to generate the constant value. * The caller must delete memory allocated for the returned string. * ------------------------------------------------------------------------ */ String *enumValue(Node *n) { String *symname = Getattr(n,"sym:name"); // Check for the %csconstvalue feature String *value = Getattr(n,"feature:cs:constvalue"); if (!value) { // The %csconst feature determines how the constant value is obtained int const_feature_flag = GetFlag(n,"feature:cs:const"); if (const_feature_flag) { // Use the C syntax to make a true C# constant and hope that it compiles as C# code value = Getattr(n,"enumvalue") ? Copy(Getattr(n,"enumvalue")) : Copy(Getattr(n,"enumvalueex")); } else { // Get the enumvalue from a PINVOKE call if (!getCurrentClass()) { // Strange hack to change the name Setattr(n,"name",Getattr(n,"value")); /* for wrapping of enums in a namespace when emit_action is used */ constantWrapper(n); value = NewStringf("%s.%s()", imclass_name, Swig_name_get(symname)); } else { memberconstantHandler(n); value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname))); } } } return value; } /* ----------------------------------------------------------------------------- * getEnumName() * ----------------------------------------------------------------------------- */ String *getEnumName(SwigType *t) { Node *enum_name = NULL; Node *n = enumLookup(t); if (n) { String *symname = Getattr(n,"sym:name"); if (symname) { // Add in class scope when referencing enum if not a global enum String *scopename_prefix = Swig_scopename_prefix(Getattr(n,"name")); String *proxyname = 0; if (scopename_prefix) { proxyname = getProxyName(scopename_prefix); } if (proxyname) enum_name = NewStringf("%s.%s", proxyname, symname); else enum_name = NewStringf("%s", symname); Delete(scopename_prefix); } } return enum_name; } /* ----------------------------------------------------------------------------- * substituteClassname() * * Substitute $csclassname with the proxy class name for classes/structs/unions that SWIG knows about. * Also substitutes enums with enum name. * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. * Inputs: * pt - parameter type * tm - cstype typemap * Outputs: * tm - cstype typemap with $csclassname substitution * Return: * substitution_performed - flag indicating if a substitution was performed * ----------------------------------------------------------------------------- */ bool substituteClassname(SwigType *pt, String *tm) { bool substitution_performed = false; SwigType *type = Copy(SwigType_typedef_resolve_all(pt)); SwigType *strippedtype = SwigType_strip_qualifiers(type); if (Strstr(tm, "$csclassname")) { SwigType *classnametype = Copy(strippedtype); substituteClassnameSpecialVariable(classnametype, tm, "$csclassname"); substitution_performed = true; Delete(classnametype); } if (Strstr(tm, "$*csclassname")) { SwigType *classnametype = Copy(strippedtype); Delete(SwigType_pop(classnametype)); substituteClassnameSpecialVariable(classnametype, tm, "$*csclassname"); substitution_performed = true; Delete(classnametype); } if (Strstr(tm, "$&csclassname")) { SwigType *classnametype = Copy(strippedtype); SwigType_add_pointer(classnametype); substituteClassnameSpecialVariable(classnametype, tm, "$&csclassname"); substitution_performed = true; Delete(classnametype); } Delete(strippedtype); Delete(type); return substitution_performed; } /* ----------------------------------------------------------------------------- * substituteClassnameSpecialVariable() * ----------------------------------------------------------------------------- */ void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) { if (SwigType_isenum(classnametype)) { String *enumname = getEnumName(classnametype); if (enumname) Replaceall(tm, classnamespecialvariable, enumname); else Replaceall(tm, classnamespecialvariable, NewStringf("int")); } else { String *classname = getProxyName(classnametype); if (classname) { Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved. String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype)); Replaceall(tm, classnamespecialvariable, descriptor); // Add to hash table so that the type wrapper classes can be created later Setattr(swig_types_hash, descriptor, classnametype); Delete(descriptor); } } } /* ----------------------------------------------------------------------------- * makeParameterName() * * Inputs: * n - Node * p - parameter node * arg_num - parameter argument number * setter - set this flag when wrapping member variables * Return: * arg - a unique parameter name * ----------------------------------------------------------------------------- */ String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) { String *arg = 0; String *pn = Getattr(p,"name"); if (setter) { // Note that in C# property setter names must always be called 'value' arg = NewString("value"); } else { // Use C parameter name unless it is a duplicate or an empty parameter name int count = 0; ParmList *plist = Getattr(n,"parms"); while (plist) { if ((Cmp(pn, Getattr(plist,"name")) == 0)) count++; plist = nextSibling(plist); } String *wrn = pn ? Swig_name_warning(p,0,pn,0) : 0; arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d",arg_num) : Copy(pn); } return arg; } /* ----------------------------------------------------------------------------- * emitTypeWrapperClass() * ----------------------------------------------------------------------------- */ void emitTypeWrapperClass(String *classname, SwigType *type) { String *swigtype = NewString(""); String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), classname); File *f_swigtype = NewFile(filen,"w"); if(!f_swigtype) { FileErrorDisplay(filen); SWIG_exit(EXIT_FAILURE); } Append(filenames_list, Copy(filen)); Delete(filen); filen = NULL; // Start writing out the type wrapper class file emitBanner(f_swigtype); if(Len(namespce) > 0) Printf(f_swigtype, "namespace %s {\n", namespce); // Pure C# baseclass and interfaces const String *pure_baseclass = typemapLookup("csbase", type, WARN_NONE); const String *pure_interfaces = typemapLookup("csinterfaces", type, WARN_NONE); // Emit the class Printv(swigtype, typemapLookup("csimports", type, WARN_NONE), // Import statements "\n", NIL); // Class attributes const String *csattributes = typemapLookup("csattributes", type, WARN_NONE); if (csattributes && *Char(csattributes)) Printf(swigtype, "%s\n", csattributes); Printv(swigtype, typemapLookup("csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers " $csclassname", // Class name and base class (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces ", " : "", pure_interfaces, " {", typemapLookup("csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class typemapLookup("cscode", type, WARN_NONE), // extra C# code "}\n", Len(namespce) > 0 ? "\n}\n" : "", NIL); Replaceall(swigtype, "$csclassname", classname); Replaceall(swigtype, "$module", module_class_name); Replaceall(swigtype, "$imclassname", imclass_name); Replaceall(swigtype, "$dllimport", dllimport); Printv(f_swigtype, swigtype, NIL); Close(f_swigtype); Delete(swigtype); } /* ----------------------------------------------------------------------------- * typemapLookup() * ----------------------------------------------------------------------------- */ const String *typemapLookup(const String *op, String *type, int warning, Node *typemap_attributes=NULL) { String *tm = NULL; const String *code = NULL; if((tm = Swig_typemap_search(op, type, NULL, NULL))) { code = Getattr(tm,"code"); if (typemap_attributes) Swig_typemap_attach_kwargs(tm,op,typemap_attributes); } if (!code) { code = empty_string; if (warning != WARN_NONE) Swig_warning(warning, input_file, line_number, "No %s typemap defined for %s\n", op, type); } return code ? code : empty_string; } /* ----------------------------------------------------------------------------- * canThrow() * Determine whether the code in the typemap can throw a C# exception. * If so, note it for later when excodeSubstitute() is called. * ----------------------------------------------------------------------------- */ void canThrow(Node *n, const String *typemap, Node *parameter) { String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap); String *canthrow = Getattr(parameter,canthrow_attribute); if (canthrow) Setattr(n,"csharp:canthrow", "1"); Delete(canthrow_attribute); } /* ----------------------------------------------------------------------------- * excodeSubstitute() * If a method can throw a C# exception, additional exception code is added to * check for the pending exception so that it can then throw the exception. The * $excode special variable is replaced by the exception code in the excode * typemap attribute. * ----------------------------------------------------------------------------- */ void excodeSubstitute(Node *n, String *code, const String *typemap, Node *parameter) { String *excode_attribute = NewStringf("tmap:%s:excode", typemap); String *excode = Getattr(parameter, excode_attribute); if (Getattr(n,"csharp:canthrow")) { int count = Replaceall(code, "$excode", excode); if (count < 1 || !excode) { Swig_warning(WARN_CSHARP_EXCODE, input_file, line_number, "C# exception may not be thrown - no $excode or excode attribute in '%s' typemap.\n", typemap); } } else { Replaceall(code, "$excode", empty_string); } Delete(excode_attribute); } }; /* class CSHARP */ /* ----------------------------------------------------------------------------- * swig_csharp() - Instantiate module * ----------------------------------------------------------------------------- */ static Language * new_swig_csharp() { return new CSHARP(); } extern "C" Language * swig_csharp(void) { return new_swig_csharp(); } /* ----------------------------------------------------------------------------- * Static member variables * ----------------------------------------------------------------------------- */ const char *CSHARP::usage = (char*)"\ C# Options (available with -csharp)\n\ -dllimport
- Override DllImport attribute name to
\n\ -namespace - Generate wrappers into C# namespace \n\ -noproxy - Generate the low-level functional interface instead\n\ of proxy classes\n\ -oldvarnames - old intermediary method names for variable wrappers\n\ \n";