1 /* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
7 * C# language module for SWIG.
8 * ----------------------------------------------------------------------------- */
10 char cvsroot_csharp_cxx[] = "$Id: csharp.cxx 11583 2009-08-15 23:22:20Z wsfulton $";
13 #include <limits.h> // for INT_MAX
17 /* Hash type used for upcalls from C/C++ */
18 typedef DOH UpcallData;
20 class CSHARP:public Language {
21 static const char *usage;
22 const String *empty_string;
23 const String *public_string;
24 const String *protected_string;
26 Hash *swig_types_hash;
37 bool proxy_flag; // Flag for generating proxy classes
38 bool native_function_flag; // Flag for when wrapping a native function
39 bool enum_constant_flag; // Flag for when wrapping an enum or constant
40 bool static_flag; // Flag for when wrapping a static functions or member variables
41 bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
42 bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
43 bool global_variable_flag; // Flag for when wrapping a global variable
44 bool old_variable_names; // Flag for old style variable names in the intermediary class
45 bool generate_property_declaration_flag; // Flag for generating properties
47 String *imclass_name; // intermediary class name
48 String *module_class_name; // module class name
49 String *imclass_class_code; // intermediary class code
50 String *proxy_class_def;
51 String *proxy_class_code;
52 String *module_class_code;
53 String *proxy_class_name;
54 String *variable_name; //Name of a variable being wrapped
55 String *proxy_class_constants_code;
56 String *module_class_constants_code;
58 String *dllimport; // DllImport attribute name
59 String *namespce; // Optional namespace name
60 String *imclass_imports; //intermediary class imports from %pragma
61 String *module_imports; //module imports from %pragma
62 String *imclass_baseclass; //inheritance for intermediary class class from %pragma
63 String *module_baseclass; //inheritance for module class from %pragma
64 String *imclass_interfaces; //interfaces for intermediary class class from %pragma
65 String *module_interfaces; //interfaces for module class from %pragma
66 String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma
67 String *module_class_modifiers; //class modifiers for module class overriden by %pragma
68 String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
69 String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
70 String *director_callback_typedefs; // Director function pointer typedefs for callbacks
71 String *director_callbacks; // Director callback function pointer member variables
72 String *director_delegate_callback; // Director callback method that delegates are set to call
73 String *director_delegate_definitions; // Director delegates definitions in proxy class
74 String *director_delegate_instances; // Director delegates member variables in proxy class
75 String *director_method_types; // Director method types
76 String *director_connect_parms; // Director delegates parameter list for director connect call
77 String *destructor_call; //C++ destructor call if any
79 // Director method stuff:
84 int first_class_dmethod;
85 int curr_class_dmethod;
87 enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
89 static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) {
90 Parm *p = NewParm(type, name);
91 Setfile(p, Getfile(n));
92 Setline(p, Getline(n));
98 /* -----------------------------------------------------------------------------
100 * ----------------------------------------------------------------------------- */
102 CSHARP():empty_string(NewString("")),
103 public_string(NewString("public")),
104 protected_string(NewString("protected")),
105 swig_types_hash(NULL),
114 filenames_list(NULL),
116 native_function_flag(false),
117 enum_constant_flag(false),
119 variable_wrapper_flag(false),
120 wrapping_member_flag(false),
121 global_variable_flag(false),
122 old_variable_names(false),
123 generate_property_declaration_flag(false),
125 module_class_name(NULL),
126 imclass_class_code(NULL),
127 proxy_class_def(NULL),
128 proxy_class_code(NULL),
129 module_class_code(NULL),
130 proxy_class_name(NULL),
132 proxy_class_constants_code(NULL),
133 module_class_constants_code(NULL),
137 imclass_imports(NULL),
138 module_imports(NULL),
139 imclass_baseclass(NULL),
140 module_baseclass(NULL),
141 imclass_interfaces(NULL),
142 module_interfaces(NULL),
143 imclass_class_modifiers(NULL),
144 module_class_modifiers(NULL),
146 imclass_cppcasts_code(NULL),
147 director_callback_typedefs(NULL),
148 director_callbacks(NULL),
149 director_delegate_callback(NULL),
150 director_delegate_definitions(NULL),
151 director_delegate_instances(NULL),
152 director_method_types(NULL),
153 director_connect_parms(NULL),
154 destructor_call(NULL),
156 dmethods_table(NULL),
159 /* for now, multiple inheritance in directors is disabled, this
160 should be easy to implement though */
161 director_multiple_inheritance = 0;
162 director_language = 1;
165 /* -----------------------------------------------------------------------------
168 * Test to see if a type corresponds to something wrapped with a proxy class
169 * Return NULL if not otherwise the proxy class name
170 * ----------------------------------------------------------------------------- */
172 String *getProxyName(SwigType *t) {
174 Node *n = classLookup(t);
176 return Getattr(n, "sym:name");
182 /* -----------------------------------------------------------------------------
183 * directorClassName()
184 * ----------------------------------------------------------------------------- */
186 String *directorClassName(Node *n) {
187 String *dirclassname;
188 const char *attrib = "director:classname";
190 if (!(dirclassname = Getattr(n, attrib))) {
191 String *classname = Getattr(n, "sym:name");
193 dirclassname = NewStringf("SwigDirector_%s", classname);
194 Setattr(n, attrib, dirclassname);
200 /* ------------------------------------------------------------
202 * ------------------------------------------------------------ */
204 virtual void main(int argc, char *argv[]) {
206 SWIG_library_directory("csharp");
208 // Look for certain command line options
209 for (int i = 1; i < argc; i++) {
211 if (strcmp(argv[i], "-dllimport") == 0) {
213 dllimport = NewString("");
214 Printf(dllimport, argv[i + 1]);
216 Swig_mark_arg(i + 1);
221 } else if (strcmp(argv[i], "-namespace") == 0) {
223 namespce = NewString("");
224 Printf(namespce, argv[i + 1]);
226 Swig_mark_arg(i + 1);
231 } else if ((strcmp(argv[i], "-noproxy") == 0)) {
234 } else if (strcmp(argv[i], "-oldvarnames") == 0) {
236 old_variable_names = true;
237 } else if (strcmp(argv[i], "-help") == 0) {
238 Printf(stdout, "%s\n", usage);
243 // Add a symbol to the parser for conditional compilation
244 Preprocessor_define("SWIGCSHARP 1", 0);
246 // Add typemap definitions
247 SWIG_typemap_lang("csharp");
248 SWIG_config_file("csharp.swg");
253 /* ---------------------------------------------------------------------
255 * --------------------------------------------------------------------- */
257 virtual int top(Node *n) {
259 // Get any options set in the module directive
260 Node *optionsnode = Getattr(Getattr(n, "module"), "options");
263 if (Getattr(optionsnode, "imclassname"))
264 imclass_name = Copy(Getattr(optionsnode, "imclassname"));
265 /* check if directors are enabled for this module. note: this
266 * is a "master" switch, without which no director code will be
267 * emitted. %feature("director") statements are also required
268 * to enable directors for individual classes or methods.
270 * use %module(directors="1") modulename at the start of the
271 * interface file to enable director generation.
273 if (Getattr(optionsnode, "directors")) {
276 if (Getattr(optionsnode, "dirprot")) {
279 allow_allprotected(GetFlag(optionsnode, "allprotected"));
282 /* Initialize all of the output files */
283 String *outfile = Getattr(n, "outfile");
284 String *outfile_h = Getattr(n, "outfile_h");
287 Printf(stderr, "Unable to determine outfile\n");
288 SWIG_exit(EXIT_FAILURE);
291 f_begin = NewFile(outfile, "w", SWIG_output_files());
293 FileErrorDisplay(outfile);
294 SWIG_exit(EXIT_FAILURE);
297 if (directorsEnabled()) {
299 Printf(stderr, "Unable to determine outfile_h\n");
300 SWIG_exit(EXIT_FAILURE);
302 f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
304 FileErrorDisplay(outfile_h);
305 SWIG_exit(EXIT_FAILURE);
309 f_runtime = NewString("");
310 f_init = NewString("");
311 f_header = NewString("");
312 f_wrappers = NewString("");
313 f_directors_h = NewString("");
314 f_directors = NewString("");
316 /* Register file targets with the SWIG file handler */
317 Swig_register_filebyname("header", f_header);
318 Swig_register_filebyname("wrapper", f_wrappers);
319 Swig_register_filebyname("begin", f_begin);
320 Swig_register_filebyname("runtime", f_runtime);
321 Swig_register_filebyname("init", f_init);
322 Swig_register_filebyname("director", f_directors);
323 Swig_register_filebyname("director_h", f_directors_h);
325 swig_types_hash = NewHash();
326 filenames_list = NewList();
328 // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
330 imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name"));
331 module_class_name = Copy(Getattr(n, "name"));
333 // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
334 if (Cmp(imclass_name, Getattr(n, "name")) == 0)
335 module_class_name = NewStringf("%sModule", Getattr(n, "name"));
337 module_class_name = Copy(Getattr(n, "name"));
340 imclass_class_code = NewString("");
341 proxy_class_def = NewString("");
342 proxy_class_code = NewString("");
343 module_class_constants_code = NewString("");
344 imclass_baseclass = NewString("");
345 imclass_interfaces = NewString("");
346 imclass_class_modifiers = NewString("");
347 module_class_code = NewString("");
348 module_baseclass = NewString("");
349 module_interfaces = NewString("");
350 module_imports = NewString("");
351 module_class_modifiers = NewString("");
352 imclass_imports = NewString("");
353 imclass_cppcasts_code = NewString("");
354 director_connect_parms = NewString("");
355 upcasts_code = NewString("");
356 dmethods_seq = NewList();
357 dmethods_table = NewHash();
361 namespce = NewString("");
363 dllimport = Copy(module_class_name);
365 Swig_banner(f_begin);
367 Printf(f_runtime, "\n");
368 Printf(f_runtime, "#define SWIGCSHARP\n");
370 if (directorsEnabled()) {
371 Printf(f_runtime, "#define SWIG_DIRECTORS\n");
373 /* Emit initial director header and director code: */
374 Swig_banner(f_directors_h);
375 Printf(f_directors_h, "\n");
376 Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
377 Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
379 Printf(f_directors, "\n\n");
380 Printf(f_directors, "/* ---------------------------------------------------\n");
381 Printf(f_directors, " * C++ director class methods\n");
382 Printf(f_directors, " * --------------------------------------------------- */\n\n");
384 Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
387 Printf(f_runtime, "\n");
389 Swig_name_register((char *) "wrapper", (char *) "CSharp_%f");
390 if (old_variable_names) {
391 Swig_name_register((char *) "set", (char *) "set_%v");
392 Swig_name_register((char *) "get", (char *) "get_%v");
395 Printf(f_wrappers, "\n#ifdef __cplusplus\n");
396 Printf(f_wrappers, "extern \"C\" {\n");
397 Printf(f_wrappers, "#endif\n\n");
402 if (directorsEnabled()) {
403 // Insert director runtime into the f_runtime file (make it occur before %header section)
404 Swig_insert_file("director.swg", f_runtime);
406 // Generate the intermediary class
408 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name);
409 File *f_im = NewFile(filen, "w", SWIG_output_files());
411 FileErrorDisplay(filen);
412 SWIG_exit(EXIT_FAILURE);
414 Append(filenames_list, Copy(filen));
418 // Start writing out the intermediary class file
421 addOpenNamespace(namespce, f_im);
424 Printf(f_im, "%s\n", imclass_imports);
426 if (Len(imclass_class_modifiers) > 0)
427 Printf(f_im, "%s ", imclass_class_modifiers);
428 Printf(f_im, "%s ", imclass_name);
430 if (imclass_baseclass && *Char(imclass_baseclass))
431 Printf(f_im, ": %s ", imclass_baseclass);
432 if (Len(imclass_interfaces) > 0)
433 Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
436 // Add the intermediary class methods
437 Replaceall(imclass_class_code, "$module", module_class_name);
438 Replaceall(imclass_class_code, "$imclassname", imclass_name);
439 Replaceall(imclass_class_code, "$dllimport", dllimport);
440 Printv(f_im, imclass_class_code, NIL);
441 Printv(f_im, imclass_cppcasts_code, NIL);
443 // Finish off the class
445 addCloseNamespace(namespce, f_im);
450 // Generate the C# module class
452 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name);
453 File *f_module = NewFile(filen, "w", SWIG_output_files());
455 FileErrorDisplay(filen);
456 SWIG_exit(EXIT_FAILURE);
458 Append(filenames_list, Copy(filen));
462 // Start writing out the module class file
463 emitBanner(f_module);
465 addOpenNamespace(namespce, f_module);
468 Printf(f_module, "%s\n", module_imports);
470 if (Len(module_class_modifiers) > 0)
471 Printf(f_module, "%s ", module_class_modifiers);
472 Printf(f_module, "%s ", module_class_name);
474 if (module_baseclass && *Char(module_baseclass))
475 Printf(f_module, ": %s ", module_baseclass);
476 if (Len(module_interfaces) > 0)
477 Printv(f_module, "implements ", module_interfaces, " ", NIL);
478 Printf(f_module, "{\n");
480 Replaceall(module_class_code, "$module", module_class_name);
481 Replaceall(module_class_constants_code, "$module", module_class_name);
483 Replaceall(module_class_code, "$imclassname", imclass_name);
484 Replaceall(module_class_constants_code, "$imclassname", imclass_name);
486 Replaceall(module_class_code, "$dllimport", dllimport);
487 Replaceall(module_class_constants_code, "$dllimport", dllimport);
489 // Add the wrapper methods
490 Printv(f_module, module_class_code, NIL);
492 // Write out all the global constants
493 Printv(f_module, module_class_constants_code, NIL);
495 // Finish off the class
496 Printf(f_module, "}\n");
497 addCloseNamespace(namespce, f_module);
503 Printv(f_wrappers, upcasts_code, NIL);
505 Printf(f_wrappers, "#ifdef __cplusplus\n");
506 Printf(f_wrappers, "}\n");
507 Printf(f_wrappers, "#endif\n");
509 // Output a C# type wrapper class for each SWIG type
510 for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
511 emitTypeWrapperClass(swig_type.key, swig_type.item);
514 // Check for overwriting file problems on filesystems that are case insensitive
517 for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
518 String *item1_lower = Swig_string_lower(it1.item);
519 for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
520 String *item2_lower = Swig_string_lower(it2.item);
521 if (it1.item && it2.item) {
522 if (Strcmp(item1_lower, item2_lower) == 0) {
523 Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
524 "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
525 "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
533 Delete(swig_types_hash);
534 swig_types_hash = NULL;
535 Delete(filenames_list);
536 filenames_list = NULL;
537 Delete(imclass_name);
539 Delete(imclass_class_code);
540 imclass_class_code = NULL;
541 Delete(proxy_class_def);
542 proxy_class_def = NULL;
543 Delete(proxy_class_code);
544 proxy_class_code = NULL;
545 Delete(module_class_constants_code);
546 module_class_constants_code = NULL;
547 Delete(imclass_baseclass);
548 imclass_baseclass = NULL;
549 Delete(imclass_interfaces);
550 imclass_interfaces = NULL;
551 Delete(imclass_class_modifiers);
552 imclass_class_modifiers = NULL;
553 Delete(module_class_name);
554 module_class_name = NULL;
555 Delete(module_class_code);
556 module_class_code = NULL;
557 Delete(module_baseclass);
558 module_baseclass = NULL;
559 Delete(module_interfaces);
560 module_interfaces = NULL;
561 Delete(module_imports);
562 module_imports = NULL;
563 Delete(module_class_modifiers);
564 module_class_modifiers = NULL;
565 Delete(imclass_imports);
566 imclass_imports = NULL;
567 Delete(imclass_cppcasts_code);
568 imclass_cppcasts_code = NULL;
569 Delete(upcasts_code);
571 Delete(dmethods_seq);
573 Delete(dmethods_table);
574 dmethods_table = NULL;
579 /* Close all of the files */
580 Dump(f_runtime, f_begin);
581 Dump(f_header, f_begin);
583 if (directorsEnabled()) {
584 Dump(f_directors, f_begin);
585 Dump(f_directors_h, f_runtime_h);
587 Printf(f_runtime_h, "\n");
588 Printf(f_runtime_h, "#endif\n");
595 Delete(f_directors_h);
596 f_directors_h = NULL;
599 Dump(f_wrappers, f_begin);
600 Wrapper_pretty_print(f_init, f_begin);
610 /* -----------------------------------------------------------------------------
612 * ----------------------------------------------------------------------------- */
614 void emitBanner(File *f) {
615 Printf(f, "/* ----------------------------------------------------------------------------\n");
616 Swig_banner_target_lang(f, " *");
617 Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
620 /*-----------------------------------------------------------------------
621 * Add new director upcall signature
622 *----------------------------------------------------------------------*/
624 UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) {
626 String *imclass_methodidx;
627 String *class_methodidx;
629 String *key = NewStringf("%s|%s", imclass_method, decl);
631 ++curr_class_dmethod;
633 /* Do we know about this director class already? */
634 if ((udata = Getattr(dmethods_table, key))) {
636 return Getattr(udata, "methodoff");
639 imclass_methodidx = NewStringf("%d", n_dmethods);
640 class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
643 new_udata = NewHash();
644 Append(dmethods_seq, new_udata);
645 Setattr(dmethods_table, key, new_udata);
647 Setattr(new_udata, "method", Copy(class_method));
648 // TODO: remove fdesc
649 // Setattr(new_udata, "fdesc", Copy(class_desc));
650 // Setattr(new_udata, "imclass_method", Copy(imclass_method));
651 // Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
652 Setattr(new_udata, "class_methodidx", class_methodidx);
653 Setattr(new_udata, "decl", Copy(decl));
654 Setattr(new_udata, "overname", Copy(overloaded_name));
660 /*-----------------------------------------------------------------------
661 * Get director upcall signature
662 *----------------------------------------------------------------------*/
665 UpcallData * getUpcallMethodData(String *director_class, String *decl) {
666 String *key = NewStringf("%s|%s", director_class, decl);
667 UpcallData *udata = Getattr(dmethods_table, key);
674 /* ----------------------------------------------------------------------
676 * ---------------------------------------------------------------------- */
678 virtual int nativeWrapper(Node *n) {
679 String *wrapname = Getattr(n, "wrap:name");
681 if (!addSymbol(wrapname, n))
684 if (Getattr(n, "type")) {
685 Swig_save("nativeWrapper", n, "name", NIL);
686 Setattr(n, "name", wrapname);
687 native_function_flag = true;
690 native_function_flag = false;
692 Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n, "wrap:name"));
698 /* ----------------------------------------------------------------------
700 * ---------------------------------------------------------------------- */
702 virtual int functionWrapper(Node *n) {
703 String *symname = Getattr(n, "sym:name");
704 SwigType *t = Getattr(n, "type");
705 ParmList *l = Getattr(n, "parms");
709 String *c_return_type = NewString("");
710 String *im_return_type = NewString("");
711 String *cleanup = NewString("");
712 String *outarg = NewString("");
713 String *body = NewString("");
714 String *im_outattributes = 0;
715 int num_arguments = 0;
716 int num_required = 0;
718 String *overloaded_name = getOverloadedName(n);
720 if (!Getattr(n, "sym:overloaded")) {
721 if (!addSymbol(Getattr(n, "sym:name"), n))
726 The rest of this function deals with generating the intermediary class wrapper function (that wraps
727 a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
728 matching PInvoke c function call.
731 // A new wrapper function object
732 Wrapper *f = NewWrapper();
734 // Make a wrapper name for this function
735 String *wname = Swig_name_wrapper(overloaded_name);
737 /* Attach the non-standard typemaps to the parameter list. */
738 Swig_typemap_attach_parms("ctype", l, f);
739 Swig_typemap_attach_parms("imtype", l, f);
741 /* Get return types */
742 if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
743 String *ctypeout = Getattr(n, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
746 Printf(c_return_type, "%s", tm);
748 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t, 0));
751 if ((tm = Swig_typemap_lookup("imtype", n, "", 0))) {
752 String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
755 Printf(im_return_type, "%s", tm);
756 im_outattributes = Getattr(n, "tmap:imtype:outattributes");
758 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
761 is_void_return = (Cmp(c_return_type, "void") == 0);
763 Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
765 Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
767 // Emit all of the local variables for holding arguments.
768 emit_parameter_variables(l, f);
770 /* Attach the standard typemaps */
771 emit_attach_parmmaps(l, f);
773 // Parameter overloading
774 Setattr(n, "wrap:parms", l);
775 Setattr(n, "wrap:name", wname);
777 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
778 if (Getattr(n, "sym:overloaded")) {
779 // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
780 Swig_overload_check(n);
781 if (Getattr(n, "overload:ignore"))
785 Printv(imclass_class_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", overloaded_name, "\")]\n", NIL);
787 if (im_outattributes)
788 Printf(imclass_class_code, " %s\n", im_outattributes);
790 Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name);
793 /* Get number of required and total arguments */
794 num_arguments = emit_num_arguments(l);
795 num_required = emit_num_required(l);
798 // Now walk the function parameter list and generate code to get arguments
799 for (i = 0, p = l; i < num_arguments; i++) {
801 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
802 p = Getattr(p, "tmap:in:next");
805 SwigType *pt = Getattr(p, "type");
806 String *ln = Getattr(p, "lname");
807 String *im_param_type = NewString("");
808 String *c_param_type = NewString("");
809 String *arg = NewString("");
811 Printf(arg, "j%s", ln);
813 /* Get the ctype types of the parameter */
814 if ((tm = Getattr(p, "tmap:ctype"))) {
815 Printv(c_param_type, tm, NIL);
817 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
820 /* Get the intermediary class parameter types of the parameter */
821 if ((tm = Getattr(p, "tmap:imtype"))) {
822 const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
823 Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
825 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
828 /* Add parameter to intermediary class method */
830 Printf(imclass_class_code, ", ");
831 Printf(imclass_class_code, "%s %s", im_param_type, arg);
833 // Add parameter to C function
834 Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
838 // Get typemap for this argument
839 if ((tm = Getattr(p, "tmap:in"))) {
840 canThrow(n, "in", p);
841 Replaceall(tm, "$source", arg); /* deprecated */
842 Replaceall(tm, "$target", ln); /* deprecated */
843 Replaceall(tm, "$arg", arg); /* deprecated? */
844 Replaceall(tm, "$input", arg);
845 Setattr(p, "emit:input", arg);
846 Printf(f->code, "%s\n", tm);
847 p = Getattr(p, "tmap:in:next");
849 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
852 Delete(im_param_type);
853 Delete(c_param_type);
857 /* Insert constraint checking code */
859 if ((tm = Getattr(p, "tmap:check"))) {
860 canThrow(n, "check", p);
861 Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
862 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
863 Replaceall(tm, "$input", Getattr(p, "emit:input"));
864 Printv(f->code, tm, "\n", NIL);
865 p = Getattr(p, "tmap:check:next");
871 /* Insert cleanup code */
873 if ((tm = Getattr(p, "tmap:freearg"))) {
874 canThrow(n, "freearg", p);
875 Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
876 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
877 Replaceall(tm, "$input", Getattr(p, "emit:input"));
878 Printv(cleanup, tm, "\n", NIL);
879 p = Getattr(p, "tmap:freearg:next");
885 /* Insert argument output code */
887 if ((tm = Getattr(p, "tmap:argout"))) {
888 canThrow(n, "argout", p);
889 Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
890 Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
891 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
892 Replaceall(tm, "$result", "jresult");
893 Replaceall(tm, "$input", Getattr(p, "emit:input"));
894 Printv(outarg, tm, "\n", NIL);
895 p = Getattr(p, "tmap:argout:next");
901 // Look for usage of throws typemap and the canthrow flag
902 ParmList *throw_parm_list = NULL;
903 if ((throw_parm_list = Getattr(n, "catchlist"))) {
904 Swig_typemap_attach_parms("throws", throw_parm_list, f);
905 for (p = throw_parm_list; p; p = nextSibling(p)) {
906 if ((tm = Getattr(p, "tmap:throws"))) {
907 canThrow(n, "throws", p);
912 String *null_attribute = 0;
913 // Now write code to make the function call
914 if (!native_function_flag) {
915 if (Cmp(nodeType(n), "constant") == 0) {
916 // Wrapping a constant hack
917 Swig_save("functionWrapper", n, "wrap:action", NIL);
919 // below based on Swig_VargetToFunction()
920 SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
921 Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
924 Swig_director_emit_dynamic_cast(n, f);
925 String *actioncode = emit_action(n);
927 if (Cmp(nodeType(n), "constant") == 0)
930 /* Return value if necessary */
931 if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
932 canThrow(n, "out", n);
933 Replaceall(tm, "$source", "result"); /* deprecated */
934 Replaceall(tm, "$target", "jresult"); /* deprecated */
935 Replaceall(tm, "$result", "jresult");
937 if (GetFlag(n, "feature:new"))
938 Replaceall(tm, "$owner", "1");
940 Replaceall(tm, "$owner", "0");
942 Printf(f->code, "%s", tm);
943 null_attribute = Getattr(n, "tmap:out:null");
945 Printf(f->code, "\n");
947 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"));
949 emit_return_variable(n, t, f);
952 /* Output argument output code */
953 Printv(f->code, outarg, NIL);
955 /* Output cleanup code */
956 Printv(f->code, cleanup, NIL);
958 /* Look to see if there is any newfree cleanup code */
959 if (GetFlag(n, "feature:new")) {
960 if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
961 canThrow(n, "newfree", n);
962 Replaceall(tm, "$source", "result"); /* deprecated */
963 Printf(f->code, "%s\n", tm);
967 /* See if there is any return cleanup code */
968 if (!native_function_flag) {
969 if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
970 canThrow(n, "ret", n);
971 Replaceall(tm, "$source", "result"); /* deprecated */
972 Printf(f->code, "%s\n", tm);
976 /* Finish C function and intermediary class function definitions */
977 Printf(imclass_class_code, ")");
978 Printf(imclass_class_code, ";\n");
980 Printf(f->def, ") {");
983 Printv(f->code, " return jresult;\n", NIL);
984 Printf(f->code, "}\n");
986 /* Substitute the cleanup code */
987 Replaceall(f->code, "$cleanup", cleanup);
989 /* Substitute the function name */
990 Replaceall(f->code, "$symname", symname);
992 /* Contract macro modification */
993 if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
994 Setattr(n, "csharp:canthrow", "1");
998 Replaceall(f->code, "$null", "0");
1000 Replaceall(f->code, "$null", null_attribute);
1002 /* Dump the function out */
1003 if (!native_function_flag) {
1004 Wrapper_print(f, f_wrappers);
1006 // Handle %csexception which sets the canthrow attribute
1007 if (Getattr(n, "feature:except:canthrow"))
1008 Setattr(n, "csharp:canthrow", "1");
1010 // A very simple check (it is not foolproof) to help typemap/feature writers for
1011 // throwing C# exceptions from unmanaged code. It checks for the common methods which
1012 // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set
1013 // so that code which checks for pending exceptions is added in the C# proxy method.
1014 if (!Getattr(n, "csharp:canthrow")) {
1015 if (Strstr(f->code, "SWIG_exception")) {
1016 Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
1017 "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n");
1018 } else if (Strstr(f->code, "SWIG_CSharpSetPendingException")) {
1019 Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
1020 "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n");
1025 if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1026 moduleClassFunctionHandler(n);
1030 * Generate the proxy class properties for public member variables.
1031 * Not for enums and constants.
1033 if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1034 // Capitalize the first letter in the variable in the getter/setter function name
1035 bool getter_flag = Cmp(symname, Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) != 0;
1037 String *getter_setter_name = NewString("");
1039 Printf(getter_setter_name, "set");
1041 Printf(getter_setter_name, "get");
1042 Putc(toupper((int) *Char(variable_name)), getter_setter_name);
1043 Printf(getter_setter_name, "%s", Char(variable_name) + 1);
1045 Setattr(n, "proxyfuncname", getter_setter_name);
1046 Setattr(n, "imfuncname", symname);
1048 proxyClassFunctionHandler(n);
1049 Delete(getter_setter_name);
1052 Delete(c_return_type);
1053 Delete(im_return_type);
1057 Delete(overloaded_name);
1062 /* -----------------------------------------------------------------------
1064 * ----------------------------------------------------------------------- */
1066 virtual int variableWrapper(Node *n) {
1067 Language::variableWrapper(n);
1071 /* -----------------------------------------------------------------------
1072 * globalvariableHandler()
1073 * ------------------------------------------------------------------------ */
1075 virtual int globalvariableHandler(Node *n) {
1077 generate_property_declaration_flag = true;
1078 variable_name = Getattr(n, "sym:name");
1079 global_variable_flag = true;
1080 int ret = Language::globalvariableHandler(n);
1081 global_variable_flag = false;
1082 generate_property_declaration_flag = false;
1085 Printf(module_class_code, "\n }\n\n");
1091 /* ----------------------------------------------------------------------
1094 * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
1095 * 1) Simple enums - simple constant within the proxy class or module class
1096 * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
1097 * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
1098 * 4) Proper enums - proper C# enum
1099 * Anonymous enums always default to 1)
1100 * ---------------------------------------------------------------------- */
1102 virtual int enumDeclaration(Node *n) {
1105 if (getCurrentClass() && (cplus_mode != PUBLIC))
1108 enum_code = NewString("");
1109 String *symname = Getattr(n, "sym:name");
1110 String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
1111 EnumFeature enum_feature = decodeEnumFeature(n);
1112 String *typemap_lookup_type = Getattr(n, "name");
1114 if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1115 // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
1117 // Pure C# baseclass and interfaces
1118 const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE);
1119 const String *pure_interfaces = typemapLookup(n, "csinterfaces", typemap_lookup_type, WARN_NONE);
1122 const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
1123 if (csattributes && *Char(csattributes))
1124 Printf(enum_code, "%s\n", csattributes);
1127 Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
1128 " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
1129 ", " : "", pure_interfaces, " {\n", NIL);
1131 // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
1132 if (symname && !Getattr(n, "unnamedinstance"))
1133 Printf(constants_code, " // %s \n", symname);
1136 // Emit each enum item
1137 Language::enumDeclaration(n);
1139 if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1140 // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
1141 // Finish the enum declaration
1142 // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
1143 Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
1144 typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
1147 Replaceall(enum_code, "$csclassname", symname);
1149 // Substitute $enumvalues - intended usage is for typesafe enums
1150 if (Getattr(n, "enumvalues"))
1151 Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
1153 Replaceall(enum_code, "$enumvalues", "");
1155 if (proxy_flag && is_wrapping_class()) {
1156 // Enums defined within the C++ class are defined within the proxy class
1158 // Add extra indentation
1159 Replaceall(enum_code, "\n", "\n ");
1160 Replaceall(enum_code, " \n", "\n");
1162 Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
1164 // Global enums are defined in their own file
1165 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), symname);
1166 File *f_enum = NewFile(filen, "w", SWIG_output_files());
1168 FileErrorDisplay(filen);
1169 SWIG_exit(EXIT_FAILURE);
1171 Append(filenames_list, Copy(filen));
1175 // Start writing out the enum file
1178 addOpenNamespace(namespce, f_enum);
1180 Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
1181 "\n", enum_code, "\n", NIL);
1183 addCloseNamespace(namespce, f_enum);
1188 // Wrap C++ enum with simple constant
1189 Printf(enum_code, "\n");
1190 if (proxy_flag && is_wrapping_class())
1191 Printv(proxy_class_constants_code, enum_code, NIL);
1193 Printv(module_class_constants_code, enum_code, NIL);
1202 /* ----------------------------------------------------------------------
1203 * enumvalueDeclaration()
1204 * ---------------------------------------------------------------------- */
1206 virtual int enumvalueDeclaration(Node *n) {
1207 if (getCurrentClass() && (cplus_mode != PUBLIC))
1210 Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
1211 String *symname = Getattr(n, "sym:name");
1212 String *value = Getattr(n, "value");
1213 String *name = Getattr(n, "name");
1216 // Strange hack from parent method
1218 tmpValue = NewString(value);
1220 tmpValue = NewString(name);
1221 // Note that this is used in enumValue() amongst other places
1222 Setattr(n, "value", tmpValue);
1225 EnumFeature enum_feature = decodeEnumFeature(parentNode(n));
1227 if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1228 // Wrap (non-anonymous) C/C++ enum with a proper C# enum
1229 // Emit the enum item.
1230 if (!GetFlag(n, "firstenumitem"))
1231 Printf(enum_code, ",\n");
1232 Printf(enum_code, " %s", symname);
1234 // Check for the %csconstvalue feature
1235 String *value = Getattr(n, "feature:cs:constvalue");
1237 // Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
1238 value = value ? value : Getattr(n, "enumvalue");
1240 Printf(enum_code, " = %s", value);
1243 // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
1244 const String *parent_name = Getattr(parentNode(n), "name");
1245 String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int");
1246 const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF);
1247 String *return_type = Copy(tm);
1248 Delete(typemap_lookup_type);
1249 typemap_lookup_type = NULL;
1251 // The %csconst feature determines how the constant value is obtained
1252 int const_feature_flag = GetFlag(n, "feature:cs:const");
1254 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
1255 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1257 if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1258 // Wrap (non-anonymouse) enum using the typesafe enum pattern
1259 if (Getattr(n, "enumvalue")) {
1260 String *value = enumValue(n);
1261 Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
1264 Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
1267 // Simple integer constants
1268 // Note these are always generated for anonymous enums, no matter what enum_feature is specified
1269 // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
1270 const char *const_readonly = const_feature_flag ? "const" : "static readonly";
1271 String *value = enumValue(n);
1272 Printf(enum_code, " %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value);
1277 // Add the enum value to the comma separated list being constructed in the enum declaration.
1278 String *enumvalues = Getattr(parentNode(n), "enumvalues");
1280 Setattr(parentNode(n), "enumvalues", Copy(symname));
1282 Printv(enumvalues, ", ", symname, NIL);
1290 /* -----------------------------------------------------------------------
1292 * Used for wrapping constants - #define or %constant.
1293 * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
1294 * C# static const variables are generated for these.
1295 * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
1296 * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
1297 * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
1298 * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
1299 * ------------------------------------------------------------------------ */
1301 virtual int constantWrapper(Node *n) {
1302 String *symname = Getattr(n, "sym:name");
1303 SwigType *t = Getattr(n, "type");
1304 ParmList *l = Getattr(n, "parms");
1306 String *return_type = NewString("");
1307 String *constants_code = NewString("");
1309 if (!addSymbol(symname, n))
1312 bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
1314 // The %csconst feature determines how the constant value is obtained
1315 int const_feature_flag = GetFlag(n, "feature:cs:const");
1317 /* Adjust the enum type for the Swig_typemap_lookup.
1318 * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
1320 t = Getattr(parentNode(n), "enumtype");
1321 Setattr(n, "type", t);
1324 /* Attach the non-standard typemaps to the parameter list. */
1325 Swig_typemap_attach_parms("cstype", l, NULL);
1327 /* Get C# return types */
1328 bool classname_substituted_flag = false;
1330 if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
1331 String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
1334 classname_substituted_flag = substituteClassname(t, tm);
1335 Printf(return_type, "%s", tm);
1337 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
1340 // Add the stripped quotes back in
1341 String *new_value = NewString("");
1342 Swig_save("constantWrapper", n, "value", NIL);
1343 if (SwigType_type(t) == T_STRING) {
1344 Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
1345 Setattr(n, "value", new_value);
1346 } else if (SwigType_type(t) == T_CHAR) {
1347 Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
1348 Setattr(n, "value", new_value);
1351 const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
1353 Printf(constants_code, " %s\n", outattributes);
1354 const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
1356 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
1357 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1359 Printf(constants_code, " %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname);
1361 // Check for the %csconstvalue feature
1362 String *value = Getattr(n, "feature:cs:constvalue");
1365 Printf(constants_code, "%s;\n", value);
1366 } else if (!const_feature_flag) {
1367 // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call.
1369 if (classname_substituted_flag) {
1370 if (SwigType_isenum(t)) {
1371 // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
1372 Printf(constants_code, "(%s)%s.%s();\n", return_type, imclass_name, Swig_name_get(symname));
1374 // This handles function pointers using the %constant directive
1375 Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
1378 Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname));
1380 // Each constant and enum value is wrapped with a separate PInvoke function call
1381 SetFlag(n, "feature:immutable");
1382 enum_constant_flag = true;
1384 enum_constant_flag = false;
1386 // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
1387 Printf(constants_code, "%s;\n", Getattr(n, "value"));
1390 // Emit the generated code to appropriate place
1391 // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed
1392 if (!is_enum_item) {
1393 if (proxy_flag && wrapping_member_flag)
1394 Printv(proxy_class_constants_code, constants_code, NIL);
1396 Printv(module_class_constants_code, constants_code, NIL);
1401 Delete(return_type);
1402 Delete(constants_code);
1406 /* -----------------------------------------------------------------------------
1408 * ----------------------------------------------------------------------------- */
1410 virtual int insertDirective(Node *n) {
1411 String *code = Getattr(n, "code");
1412 Replaceall(code, "$module", module_class_name);
1413 Replaceall(code, "$imclassname", imclass_name);
1414 Replaceall(code, "$dllimport", dllimport);
1415 return Language::insertDirective(n);
1418 /* -----------------------------------------------------------------------------
1422 * imclassbase - base (extends) for the intermediary class
1423 * imclassclassmodifiers - class modifiers for the intermediary class
1424 * imclasscode - text (C# code) is copied verbatim to the intermediary class
1425 * imclassimports - import statements for the intermediary class
1426 * imclassinterfaces - interface (implements) for the intermediary class
1428 * modulebase - base (extends) for the module class
1429 * moduleclassmodifiers - class modifiers for the module class
1430 * modulecode - text (C# code) is copied verbatim to the module class
1431 * moduleimports - import statements for the module class
1432 * moduleinterfaces - interface (implements) for the module class
1434 * ----------------------------------------------------------------------------- */
1436 virtual int pragmaDirective(Node *n) {
1438 String *lang = Getattr(n, "lang");
1439 String *code = Getattr(n, "name");
1440 String *value = Getattr(n, "value");
1442 if (Strcmp(lang, "csharp") == 0) {
1444 String *strvalue = NewString(value);
1445 Replaceall(strvalue, "\\\"", "\"");
1447 if (Strcmp(code, "imclassbase") == 0) {
1448 Delete(imclass_baseclass);
1449 imclass_baseclass = Copy(strvalue);
1450 } else if (Strcmp(code, "imclassclassmodifiers") == 0) {
1451 Delete(imclass_class_modifiers);
1452 imclass_class_modifiers = Copy(strvalue);
1453 } else if (Strcmp(code, "imclasscode") == 0) {
1454 Printf(imclass_class_code, "%s\n", strvalue);
1455 } else if (Strcmp(code, "imclassimports") == 0) {
1456 Delete(imclass_imports);
1457 imclass_imports = Copy(strvalue);
1458 } else if (Strcmp(code, "imclassinterfaces") == 0) {
1459 Delete(imclass_interfaces);
1460 imclass_interfaces = Copy(strvalue);
1461 } else if (Strcmp(code, "modulebase") == 0) {
1462 Delete(module_baseclass);
1463 module_baseclass = Copy(strvalue);
1464 } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
1465 Delete(module_class_modifiers);
1466 module_class_modifiers = Copy(strvalue);
1467 } else if (Strcmp(code, "modulecode") == 0) {
1468 Printf(module_class_code, "%s\n", strvalue);
1469 } else if (Strcmp(code, "moduleimports") == 0) {
1470 Delete(module_imports);
1471 module_imports = Copy(strvalue);
1472 } else if (Strcmp(code, "moduleinterfaces") == 0) {
1473 Delete(module_interfaces);
1474 module_interfaces = Copy(strvalue);
1476 Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
1481 return Language::pragmaDirective(n);
1484 /* -----------------------------------------------------------------------------
1485 * emitProxyClassDefAndCPPCasts()
1486 * ----------------------------------------------------------------------------- */
1488 void emitProxyClassDefAndCPPCasts(Node *n) {
1489 String *c_classname = SwigType_namestr(Getattr(n, "name"));
1490 String *c_baseclass = NULL;
1491 String *baseclass = NULL;
1492 String *c_baseclassname = NULL;
1493 SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
1494 bool feature_director = Swig_directorclass(n) ? true : false;
1496 // Inheritance from pure C# classes
1497 Node *attributes = NewHash();
1498 const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
1499 bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
1500 bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
1504 if (!purebase_replace) {
1505 List *baselist = Getattr(n, "bases");
1507 Iterator base = First(baselist);
1508 while (base.item && GetFlag(base.item, "feature:ignore")) {
1512 c_baseclassname = Getattr(base.item, "name");
1513 baseclass = Copy(getProxyName(c_baseclassname));
1515 c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
1517 /* Warn about multiple inheritance for additional base class(es) */
1519 if (GetFlag(base.item, "feature:ignore")) {
1523 String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
1524 String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
1525 Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
1526 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", proxyclassname, baseclassname);
1533 bool derived = baseclass && getProxyName(c_baseclassname);
1534 if (derived && purebase_notderived)
1535 pure_baseclass = empty_string;
1536 const String *wanted_base = baseclass ? baseclass : pure_baseclass;
1538 if (purebase_replace) {
1539 wanted_base = pure_baseclass;
1543 if (purebase_notderived)
1544 Swig_error(input_file, line_number, "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
1545 } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
1546 Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
1547 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#. "
1548 "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
1551 // Pure C# interfaces
1552 const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
1553 // Start writing the proxy class
1554 Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
1558 const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
1559 if (csattributes && *Char(csattributes))
1560 Printf(proxy_class_def, "%s\n", csattributes);
1562 Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
1563 " $csclassname", // Class name and base class
1564 (*Char(wanted_base) || *Char(pure_interfaces)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(pure_interfaces)) ? // Interfaces
1565 ", " : "", pure_interfaces, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
1566 typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
1569 // C++ destructor is wrapped by the Dispose method
1570 // Note that the method name is specified in a typemap attribute called methodname
1571 String *destruct = NewString("");
1572 const String *tm = NULL;
1573 attributes = NewHash();
1574 String *destruct_methodname = NULL;
1575 String *destruct_methodmodifiers = NULL;
1577 tm = typemapLookup(n, "csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
1578 destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname");
1579 destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct_derived:methodmodifiers");
1581 tm = typemapLookup(n, "csdestruct", typemap_lookup_type, WARN_NONE, attributes);
1582 destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname");
1583 destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct:methodmodifiers");
1585 if (tm && *Char(tm)) {
1586 if (!destruct_methodname) {
1587 Swig_error(input_file, line_number, "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
1589 if (!destruct_methodmodifiers) {
1590 Swig_error(input_file, line_number,
1591 "No methodmodifiers attribute defined in csdestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
1594 // Emit the Finalize and Dispose methods
1597 if (*Char(destructor_call)) {
1598 Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL);
1601 Printv(destruct, tm, NIL);
1602 if (*Char(destructor_call))
1603 Replaceall(destruct, "$imcall", destructor_call);
1605 Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
1606 if (*Char(destruct))
1607 Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n",
1611 if (feature_director) {
1612 // Generate director connect method
1613 // put this in classDirectorEnd ???
1614 Printf(proxy_class_code, " private void SwigDirectorConnect() {\n");
1617 for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
1618 UpcallData *udata = Getitem(dmethods_seq, i);
1619 String *method = Getattr(udata, "method");
1620 String *methid = Getattr(udata, "class_methodidx");
1621 String *overname = Getattr(udata, "overname");
1622 Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
1623 Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirector%s);\n", methid, proxy_class_name, methid, overname);
1625 Printf(proxy_class_code, " %s.%s_director_connect(swigCPtr", imclass_name, proxy_class_name);
1626 for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
1627 UpcallData *udata = Getitem(dmethods_seq, i);
1628 String *methid = Getattr(udata, "class_methodidx");
1629 Printf(proxy_class_code, ", swigDelegate%s", methid);
1631 Printf(proxy_class_code, ");\n");
1632 Printf(proxy_class_code, " }\n");
1634 if (first_class_dmethod < curr_class_dmethod) {
1635 // Only emit if there is at least one director method
1636 Printf(proxy_class_code, "\n");
1637 Printf(proxy_class_code, " private bool SwigDerivedClassHasMethod(string methodName, Type[] methodTypes) {\n");
1638 Printf(proxy_class_code,
1639 " System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, methodTypes, null);\n");
1640 Printf(proxy_class_code, " bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(%s));\n", proxy_class_name);
1641 /* Could add this code to cover corner case where the GetMethod() returns a method which allows type
1642 * promotion, eg it will return foo(double), if looking for foo(int).
1643 if (hasDerivedMethod) {
1644 hasDerivedMethod = false;
1645 if (methodInfo != null)
1647 hasDerivedMethod = true;
1648 ParameterInfo[] parameterArray1 = methodInfo.GetParameters();
1649 for (int i=0; i<methodTypes.Length; i++)
1651 if (parameterArray1[0].ParameterType != methodTypes[0])
1653 hasDerivedMethod = false;
1660 Printf(proxy_class_code, " return hasDerivedMethod;\n");
1661 Printf(proxy_class_code, " }\n");
1664 if (Len(director_delegate_callback) > 0)
1665 Printv(proxy_class_code, director_delegate_callback, NIL);
1666 if (Len(director_delegate_definitions) > 0)
1667 Printv(proxy_class_code, "\n", director_delegate_definitions, NIL);
1668 if (Len(director_delegate_instances) > 0)
1669 Printv(proxy_class_code, "\n", director_delegate_instances, NIL);
1670 if (Len(director_method_types) > 0)
1671 Printv(proxy_class_code, "\n", director_method_types, NIL);
1673 Delete(director_callback_typedefs);
1674 director_callback_typedefs = NULL;
1675 Delete(director_callbacks);
1676 director_callbacks = NULL;
1677 Delete(director_delegate_callback);
1678 director_delegate_callback = NULL;
1679 Delete(director_delegate_definitions);
1680 director_delegate_definitions = NULL;
1681 Delete(director_delegate_instances);
1682 director_delegate_instances = NULL;
1683 Delete(director_method_types);
1684 director_method_types = NULL;
1685 Delete(director_connect_parms);
1686 director_connect_parms = NULL;
1692 // Emit extra user code
1693 Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
1696 // Substitute various strings into the above template
1697 Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
1698 Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
1700 Replaceall(proxy_class_def, "$module", module_class_name);
1701 Replaceall(proxy_class_code, "$module", module_class_name);
1703 Replaceall(proxy_class_def, "$imclassname", imclass_name);
1704 Replaceall(proxy_class_code, "$imclassname", imclass_name);
1706 Replaceall(proxy_class_def, "$dllimport", dllimport);
1707 Replaceall(proxy_class_code, "$dllimport", dllimport);
1709 // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
1711 Printv(imclass_cppcasts_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", proxy_class_name, "Upcast", "\")]\n", NIL);
1712 Printf(imclass_cppcasts_code, " public static extern IntPtr $csclassnameUpcast(IntPtr objectRef);\n");
1714 Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
1716 Printv(upcasts_code,
1717 "SWIGEXPORT $cbaseclass * SWIGSTDCALL CSharp_$imclazznameUpcast",
1718 "($cclass *objectRef) {\n", " return ($cbaseclass *)objectRef;\n" "}\n", "\n", NIL);
1720 Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
1721 Replaceall(upcasts_code, "$imclazzname", proxy_class_name);
1722 Replaceall(upcasts_code, "$cclass", c_classname);
1727 /* ----------------------------------------------------------------------
1729 * ---------------------------------------------------------------------- */
1731 virtual int classHandler(Node *n) {
1733 File *f_proxy = NULL;
1735 proxy_class_name = NewString(Getattr(n, "sym:name"));
1737 if (!addSymbol(proxy_class_name, n))
1740 if (Cmp(proxy_class_name, imclass_name) == 0) {
1741 Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
1742 SWIG_exit(EXIT_FAILURE);
1745 if (Cmp(proxy_class_name, module_class_name) == 0) {
1746 Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
1747 SWIG_exit(EXIT_FAILURE);
1750 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), proxy_class_name);
1751 f_proxy = NewFile(filen, "w", SWIG_output_files());
1753 FileErrorDisplay(filen);
1754 SWIG_exit(EXIT_FAILURE);
1756 Append(filenames_list, Copy(filen));
1760 // Start writing out the proxy class file
1761 emitBanner(f_proxy);
1763 addOpenNamespace(namespce, f_proxy);
1765 Clear(proxy_class_def);
1766 Clear(proxy_class_code);
1768 destructor_call = NewString("");
1769 proxy_class_constants_code = NewString("");
1772 Language::classHandler(n);
1776 emitProxyClassDefAndCPPCasts(n);
1778 Replaceall(proxy_class_def, "$module", module_class_name);
1779 Replaceall(proxy_class_code, "$module", module_class_name);
1780 Replaceall(proxy_class_constants_code, "$module", module_class_name);
1781 Replaceall(proxy_class_def, "$imclassname", imclass_name);
1782 Replaceall(proxy_class_code, "$imclassname", imclass_name);
1783 Replaceall(proxy_class_constants_code, "$imclassname", imclass_name);
1784 Replaceall(proxy_class_def, "$dllimport", dllimport);
1785 Replaceall(proxy_class_code, "$dllimport", dllimport);
1786 Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
1788 Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
1790 // Write out all the constants
1791 if (Len(proxy_class_constants_code) != 0)
1792 Printv(f_proxy, proxy_class_constants_code, NIL);
1794 Printf(f_proxy, "}\n");
1795 addCloseNamespace(namespce, f_proxy);
1799 /* Output the downcast method, if necessary. Note: There's no other really
1800 good place to put this code, since Abstract Base Classes (ABCs) can and should have
1801 downcasts, making the constructorHandler() a bad place (because ABCs don't get to
1802 have constructors emitted.) */
1803 if (GetFlag(n, "feature:javadowncast")) {
1804 String *norm_name = SwigType_namestr(Getattr(n, "name"));
1806 Printf(imclass_class_code, " public final static native %s downcast%s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, proxy_class_name);
1808 Wrapper *dcast_wrap = NewWrapper();
1810 Printf(dcast_wrap->def, "SWIGEXPORT jobject SWIGSTDCALL CSharp_downcast%s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {",
1812 Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n");
1813 Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n");
1814 Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
1815 Printf(dcast_wrap->code, " if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
1816 Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n");
1817 Printf(dcast_wrap->code, " return jresult;\n");
1818 Printf(dcast_wrap->code, "}\n");
1820 Wrapper_print(dcast_wrap, f_wrappers);
1821 DelWrapper(dcast_wrap);
1824 emitDirectorExtraMethods(n);
1826 Delete(proxy_class_name);
1827 proxy_class_name = NULL;
1828 Delete(destructor_call);
1829 destructor_call = NULL;
1830 Delete(proxy_class_constants_code);
1831 proxy_class_constants_code = NULL;
1837 /* ----------------------------------------------------------------------
1838 * memberfunctionHandler()
1839 * ---------------------------------------------------------------------- */
1841 virtual int memberfunctionHandler(Node *n) {
1842 Language::memberfunctionHandler(n);
1845 String *overloaded_name = getOverloadedName(n);
1846 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1847 Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1848 Setattr(n, "imfuncname", intermediary_function_name);
1849 proxyClassFunctionHandler(n);
1850 Delete(overloaded_name);
1855 /* ----------------------------------------------------------------------
1856 * staticmemberfunctionHandler()
1857 * ---------------------------------------------------------------------- */
1859 virtual int staticmemberfunctionHandler(Node *n) {
1862 Language::staticmemberfunctionHandler(n);
1865 String *overloaded_name = getOverloadedName(n);
1866 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1867 Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1868 Setattr(n, "imfuncname", intermediary_function_name);
1869 proxyClassFunctionHandler(n);
1870 Delete(overloaded_name);
1872 static_flag = false;
1878 /* -----------------------------------------------------------------------------
1879 * proxyClassFunctionHandler()
1881 * Function called for creating a C# wrapper function around a c++ function in the
1882 * proxy class. Used for both static and non-static C++ class functions.
1883 * C++ class static functions map to C# static functions.
1884 * Two extra attributes in the Node must be available. These are "proxyfuncname" -
1885 * the name of the C# class proxy function, which in turn will call "imfuncname" -
1886 * the intermediary (PInvoke) function name in the intermediary class.
1887 * ----------------------------------------------------------------------------- */
1889 void proxyClassFunctionHandler(Node *n) {
1890 SwigType *t = Getattr(n, "type");
1891 ParmList *l = Getattr(n, "parms");
1892 String *intermediary_function_name = Getattr(n, "imfuncname");
1893 String *proxy_function_name = Getattr(n, "proxyfuncname");
1896 Parm *last_parm = 0;
1898 String *imcall = NewString("");
1899 String *return_type = NewString("");
1900 String *function_code = NewString("");
1901 bool setter_flag = false;
1902 String *pre_code = NewString("");
1903 String *post_code = NewString("");
1904 String *terminator_code = NewString("");
1909 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
1910 if (Getattr(n, "overload:ignore"))
1913 // Don't generate proxy method for additional explicitcall method used in directors
1914 if (GetFlag(n, "explicitcall"))
1918 if (SwigType_type(Getattr(l, "type")) == T_VOID) {
1923 /* Attach the non-standard typemaps to the parameter list */
1924 Swig_typemap_attach_parms("in", l, NULL);
1925 Swig_typemap_attach_parms("cstype", l, NULL);
1926 Swig_typemap_attach_parms("csin", l, NULL);
1928 /* Get return types */
1929 if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
1930 // 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
1931 SwigType *covariant = Getattr(n, "covariant");
1932 String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
1935 substituteClassname(covariant ? covariant : t, tm);
1936 Printf(return_type, "%s", tm);
1938 Swig_warning(WARN_CSHARP_COVARIANT_RET, input_file, line_number,
1939 "Covariant return types not supported in C#. Proxy method will return %s.\n", SwigType_str(covariant, 0));
1941 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
1944 if (wrapping_member_flag && !enum_constant_flag) {
1946 setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0);
1948 Swig_typemap_attach_parms("csvarin", l, NULL);
1951 /* Start generating the proxy function */
1952 const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
1954 Printf(function_code, " %s\n", outattributes);
1955 const String *csattributes = Getattr(n, "feature:cs:attributes");
1957 Printf(function_code, " %s\n", csattributes);
1958 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
1960 if (is_smart_pointer()) {
1961 // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
1962 String *mmods = Copy(methodmods);
1963 Replaceall(mmods, "override", "");
1964 Replaceall(mmods, "virtual", "");
1965 Replaceall(mmods, "new", "");
1966 Chop(mmods); // remove trailing whitespace
1967 Printf(function_code, " %s ", mmods);
1970 Printf(function_code, " %s ", methodmods);
1973 methodmods = (is_public(n) ? public_string : protected_string);
1974 Printf(function_code, " %s ", methodmods);
1975 if (!is_smart_pointer()) {
1976 // Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
1977 if (Getattr(n, "override"))
1978 Printf(function_code, "override ");
1979 else if (checkAttribute(n, "storage", "virtual"))
1980 Printf(function_code, "virtual ");
1981 if (Getattr(n, "hides"))
1982 Printf(function_code, "new ");
1986 Printf(function_code, "static ");
1987 Printf(function_code, "%s %s(", return_type, proxy_function_name);
1989 Printv(imcall, imclass_name, ".$imfuncname(", NIL);
1991 Printf(imcall, "swigCPtr");
1993 emit_mark_varargs(l);
1995 int gencomma = !static_flag;
1997 /* Output each parameter */
1998 for (i = 0, p = l; p; i++) {
2000 /* Ignored varargs */
2001 if (checkAttribute(p, "varargs:ignore", "1")) {
2006 /* Ignored parameters */
2007 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2008 p = Getattr(p, "tmap:in:next");
2012 /* Ignore the 'this' argument for variable wrappers */
2013 if (!(variable_wrapper_flag && i == 0)) {
2014 SwigType *pt = Getattr(p, "type");
2015 String *param_type = NewString("");
2019 /* Get the C# parameter type */
2020 if ((tm = Getattr(p, "tmap:cstype"))) {
2021 substituteClassname(pt, tm);
2022 const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
2023 Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
2025 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
2029 Printf(imcall, ", ");
2031 String *arg = makeParameterName(n, p, i, setter_flag);
2033 // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2034 if ((tm = Getattr(p, "tmap:csin"))) {
2035 substituteClassname(pt, tm);
2036 Replaceall(tm, "$csinput", arg);
2037 String *pre = Getattr(p, "tmap:csin:pre");
2039 substituteClassname(pt, pre);
2040 Replaceall(pre, "$csinput", arg);
2041 if (Len(pre_code) > 0)
2042 Printf(pre_code, "\n");
2043 Printv(pre_code, pre, NIL);
2045 String *post = Getattr(p, "tmap:csin:post");
2047 substituteClassname(pt, post);
2048 Replaceall(post, "$csinput", arg);
2049 if (Len(post_code) > 0)
2050 Printf(post_code, "\n");
2051 Printv(post_code, post, NIL);
2053 String *terminator = Getattr(p, "tmap:csin:terminator");
2055 substituteClassname(pt, terminator);
2056 Replaceall(terminator, "$csinput", arg);
2057 if (Len(terminator_code) > 0)
2058 Insert(terminator_code, 0, "\n");
2059 Insert(terminator_code, 0, terminator);
2061 Printv(imcall, tm, NIL);
2063 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
2066 /* Add parameter to proxy function */
2068 Printf(function_code, ", ");
2070 Printf(function_code, "%s %s", param_type, arg);
2075 p = Getattr(p, "tmap:in:next");
2078 Printf(imcall, ")");
2079 Printf(function_code, ")");
2081 // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
2082 if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
2083 excodeSubstitute(n, tm, "csout", n);
2084 bool is_pre_code = Len(pre_code) > 0;
2085 bool is_post_code = Len(post_code) > 0;
2086 bool is_terminator_code = Len(terminator_code) > 0;
2087 if (is_pre_code || is_post_code || is_terminator_code) {
2088 Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
2090 Insert(tm, 0, "\n try ");
2091 Printv(tm, " finally {\n", post_code, "\n }", NIL);
2093 Insert(tm, 0, "\n ");
2096 Insert(tm, 0, pre_code);
2097 Insert(tm, 0, "\n");
2099 if (is_terminator_code) {
2100 Printv(tm, "\n", terminator_code, NIL);
2105 if (GetFlag(n, "feature:new"))
2106 Replaceall(tm, "$owner", "true");
2108 Replaceall(tm, "$owner", "false");
2109 substituteClassname(t, tm);
2111 // For director methods: generate code to selectively make a normal polymorphic call or
2112 // an explicit method call - needed to prevent infinite recursion calls in director methods.
2113 Node *explicit_n = Getattr(n, "explicitcallnode");
2115 String *ex_overloaded_name = getOverloadedName(explicit_n);
2116 String *ex_intermediary_function_name = Swig_name_member(proxy_class_name, ex_overloaded_name);
2118 String *ex_imcall = Copy(imcall);
2119 Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
2120 Replaceall(imcall, "$imfuncname", intermediary_function_name);
2122 String *excode = NewString("");
2123 if (!Cmp(return_type, "void"))
2124 Printf(excode, "if (this.GetType() == typeof(%s)) %s; else %s", proxy_class_name, imcall, ex_imcall);
2126 Printf(excode, "((this.GetType() == typeof(%s)) ? %s : %s)", proxy_class_name, imcall, ex_imcall);
2129 Printv(imcall, excode, NIL);
2130 Delete(ex_overloaded_name);
2133 Replaceall(imcall, "$imfuncname", intermediary_function_name);
2135 Replaceall(tm, "$imcall", imcall);
2137 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
2140 if (wrapping_member_flag && !enum_constant_flag) {
2142 if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
2143 // Get the C# variable type - obtained differently depending on whether a setter is required.
2144 String *variable_type = return_type;
2146 p = last_parm; // (last parameter is the only parameter for properties)
2147 SwigType *pt = Getattr(p, "type");
2148 if ((tm = Getattr(p, "tmap:cstype"))) {
2149 substituteClassname(pt, tm);
2150 String *cstypeout = Getattr(p, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
2151 variable_type = cstypeout ? cstypeout : tm;
2153 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2156 const String *csattributes = Getattr(n, "feature:cs:attributes");
2158 Printf(proxy_class_code, " %s\n", csattributes);
2159 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2161 methodmods = (is_public(n) ? public_string : protected_string);
2162 Printf(proxy_class_code, " %s %s%s %s {", methodmods, static_flag ? "static " : "", variable_type, variable_name);
2164 generate_property_declaration_flag = false;
2168 p = last_parm; // (last parameter is the only parameter for properties)
2169 SwigType *pt = Getattr(p, "type");
2170 if ((tm = Getattr(p, "tmap:csvarin"))) {
2171 substituteClassname(pt, tm);
2172 Replaceall(tm, "$imcall", imcall);
2173 excodeSubstitute(n, tm, "csvarin", p);
2174 Printf(proxy_class_code, "%s", tm);
2176 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2180 if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
2181 if (GetFlag(n, "feature:new"))
2182 Replaceall(tm, "$owner", "true");
2184 Replaceall(tm, "$owner", "false");
2185 substituteClassname(t, tm);
2186 Replaceall(tm, "$imcall", imcall);
2187 excodeSubstitute(n, tm, "csvarout", n);
2188 Printf(proxy_class_code, "%s", tm);
2190 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
2194 // Normal function call
2195 Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2196 Printv(proxy_class_code, function_code, NIL);
2201 Delete(terminator_code);
2202 Delete(function_code);
2203 Delete(return_type);
2207 /* ----------------------------------------------------------------------
2208 * constructorHandler()
2209 * ---------------------------------------------------------------------- */
2211 virtual int constructorHandler(Node *n) {
2213 ParmList *l = Getattr(n, "parms");
2217 String *function_code = NewString("");
2218 String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the csin typemap has code in the pre or post attributes
2219 String *helper_args = NewString("");
2220 String *pre_code = NewString("");
2221 String *post_code = NewString("");
2222 String *terminator_code = NewString("");
2223 String *im_return_type = NewString("");
2224 bool feature_director = (parentNode(n) && Swig_directorclass(n));
2226 Language::constructorHandler(n);
2228 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
2229 if (Getattr(n, "overload:ignore"))
2233 String *overloaded_name = getOverloadedName(n);
2234 String *mangled_overname = Swig_name_construct(overloaded_name);
2235 String *imcall = NewString("");
2237 const String *csattributes = Getattr(n, "feature:cs:attributes");
2239 Printf(function_code, " %s\n", csattributes);
2240 Printf(helper_code, " %s\n", csattributes);
2242 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2243 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2245 tm = Getattr(n, "tmap:imtype"); // typemaps were attached earlier to the node
2246 String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
2249 Printf(im_return_type, "%s", tm);
2251 Printf(function_code, " %s %s(", methodmods, proxy_class_name);
2252 Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
2254 Printv(imcall, imclass_name, ".", mangled_overname, "(", NIL);
2256 /* Attach the non-standard typemaps to the parameter list */
2257 Swig_typemap_attach_parms("in", l, NULL);
2258 Swig_typemap_attach_parms("cstype", l, NULL);
2259 Swig_typemap_attach_parms("csin", l, NULL);
2261 emit_mark_varargs(l);
2265 /* Output each parameter */
2266 for (i = 0, p = l; p; i++) {
2268 /* Ignored varargs */
2269 if (checkAttribute(p, "varargs:ignore", "1")) {
2274 /* Ignored parameters */
2275 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2276 p = Getattr(p, "tmap:in:next");
2280 SwigType *pt = Getattr(p, "type");
2281 String *param_type = NewString("");
2283 /* Get the C# parameter type */
2284 if ((tm = Getattr(p, "tmap:cstype"))) {
2285 substituteClassname(pt, tm);
2286 const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
2287 Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
2289 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
2293 Printf(imcall, ", ");
2295 String *arg = makeParameterName(n, p, i, false);
2298 // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2299 if ((tm = Getattr(p, "tmap:csin"))) {
2300 substituteClassname(pt, tm);
2301 Replaceall(tm, "$csinput", arg);
2302 String *pre = Getattr(p, "tmap:csin:pre");
2304 substituteClassname(pt, pre);
2305 Replaceall(pre, "$csinput", arg);
2306 if (Len(pre_code) > 0)
2307 Printf(pre_code, "\n");
2308 Printv(pre_code, pre, NIL);
2310 String *post = Getattr(p, "tmap:csin:post");
2312 substituteClassname(pt, post);
2313 Replaceall(post, "$csinput", arg);
2314 if (Len(post_code) > 0)
2315 Printf(post_code, "\n");
2316 Printv(post_code, post, NIL);
2318 String *terminator = Getattr(p, "tmap:csin:terminator");
2320 substituteClassname(pt, terminator);
2321 Replaceall(terminator, "$csinput", arg);
2322 if (Len(terminator_code) > 0)
2323 Insert(terminator_code, 0, "\n");
2324 Insert(terminator_code, 0, terminator);
2326 cshin = Getattr(p, "tmap:csin:cshin");
2328 Replaceall(cshin, "$csinput", arg);
2329 Printv(imcall, tm, NIL);
2331 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
2334 /* Add parameter to proxy function */
2336 Printf(function_code, ", ");
2337 Printf(helper_code, ", ");
2338 Printf(helper_args, ", ");
2340 Printf(function_code, "%s %s", param_type, arg);
2341 Printf(helper_code, "%s %s", param_type, arg);
2342 Printf(helper_args, "%s", cshin ? cshin : arg);
2348 p = Getattr(p, "tmap:in:next");
2351 Printf(imcall, ")");
2353 Printf(function_code, ")");
2354 Printf(helper_code, ")");
2356 /* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */
2357 Hash *attributes = NewHash();
2358 String *construct_tm = Copy(typemapLookup(n, "csconstruct", Getattr(n, "name"),
2359 WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes));
2361 if (!feature_director) {
2362 Replaceall(construct_tm, "$directorconnect", "");
2364 String *connect_attr = Getattr(attributes, "tmap:csconstruct:directorconnect");
2367 Replaceall(construct_tm, "$directorconnect", connect_attr);
2369 Swig_warning(WARN_CSHARP_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"csconstruct\" typemap.\n",
2370 Getattr(n, "name"));
2371 Replaceall(construct_tm, "$directorconnect", "");
2375 Printv(function_code, " ", construct_tm, NIL);
2378 excodeSubstitute(n, function_code, "csconstruct", attributes);
2380 bool is_pre_code = Len(pre_code) > 0;
2381 bool is_post_code = Len(post_code) > 0;
2382 bool is_terminator_code = Len(terminator_code) > 0;
2383 if (is_pre_code || is_post_code || is_terminator_code) {
2384 Printf(helper_code, " {\n");
2386 Printv(helper_code, pre_code, "\n", NIL);
2389 Printf(helper_code, " try {\n");
2390 Printv(helper_code, " return ", imcall, ";\n", NIL);
2391 Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
2393 Printv(helper_code, " return ", imcall, ";", NIL);
2395 if (is_terminator_code) {
2396 Printv(helper_code, "\n", terminator_code, NIL);
2398 Printf(helper_code, "\n }\n");
2399 String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
2400 String *im_outattributes = Getattr(n, "tmap:imtype:outattributes");
2401 if (im_outattributes)
2402 Printf(proxy_class_code, " %s\n", im_outattributes);
2403 Printv(proxy_class_code, helper_code, "\n", NIL);
2404 Replaceall(function_code, "$imcall", helper_name);
2405 Delete(helper_name);
2407 Replaceall(function_code, "$imcall", imcall);
2410 Printv(proxy_class_code, function_code, "\n", NIL);
2412 Delete(helper_args);
2413 Delete(im_return_type);
2416 Delete(terminator_code);
2417 Delete(construct_tm);
2419 Delete(overloaded_name);
2426 /* ----------------------------------------------------------------------
2427 * destructorHandler()
2428 * ---------------------------------------------------------------------- */
2430 virtual int destructorHandler(Node *n) {
2431 Language::destructorHandler(n);
2432 String *symname = Getattr(n, "sym:name");
2435 Printv(destructor_call, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
2440 /* ----------------------------------------------------------------------
2441 * membervariableHandler()
2442 * ---------------------------------------------------------------------- */
2444 virtual int membervariableHandler(Node *n) {
2446 generate_property_declaration_flag = true;
2447 variable_name = Getattr(n, "sym:name");
2448 wrapping_member_flag = true;
2449 variable_wrapper_flag = true;
2450 Language::membervariableHandler(n);
2451 wrapping_member_flag = false;
2452 variable_wrapper_flag = false;
2453 generate_property_declaration_flag = false;
2455 Printf(proxy_class_code, "\n }\n\n");
2460 /* ----------------------------------------------------------------------
2461 * staticmembervariableHandler()
2462 * ---------------------------------------------------------------------- */
2464 virtual int staticmembervariableHandler(Node *n) {
2466 bool static_const_member_flag = (Getattr(n, "value") == 0);
2468 generate_property_declaration_flag = true;
2469 variable_name = Getattr(n, "sym:name");
2470 wrapping_member_flag = true;
2472 Language::staticmembervariableHandler(n);
2473 wrapping_member_flag = false;
2474 static_flag = false;
2475 generate_property_declaration_flag = false;
2477 if (static_const_member_flag)
2478 Printf(proxy_class_code, "\n }\n\n");
2483 /* ----------------------------------------------------------------------
2484 * memberconstantHandler()
2485 * ---------------------------------------------------------------------- */
2487 virtual int memberconstantHandler(Node *n) {
2488 variable_name = Getattr(n, "sym:name");
2489 wrapping_member_flag = true;
2490 Language::memberconstantHandler(n);
2491 wrapping_member_flag = false;
2495 /* -----------------------------------------------------------------------------
2496 * getOverloadedName()
2497 * ----------------------------------------------------------------------------- */
2499 String *getOverloadedName(Node *n) {
2501 /* A C# HandleRef is used for all classes in the SWIG intermediary class.
2502 * The intermediary class methods are thus mangled when overloaded to give
2504 String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
2506 if (Getattr(n, "sym:overloaded")) {
2507 Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
2510 return overloaded_name;
2513 /* -----------------------------------------------------------------------------
2514 * moduleClassFunctionHandler()
2515 * ----------------------------------------------------------------------------- */
2517 void moduleClassFunctionHandler(Node *n) {
2518 SwigType *t = Getattr(n, "type");
2519 ParmList *l = Getattr(n, "parms");
2522 Parm *last_parm = 0;
2524 String *imcall = NewString("");
2525 String *return_type = NewString("");
2526 String *function_code = NewString("");
2527 int num_arguments = 0;
2528 int num_required = 0;
2529 String *overloaded_name = getOverloadedName(n);
2530 String *func_name = NULL;
2531 bool setter_flag = false;
2532 String *pre_code = NewString("");
2533 String *post_code = NewString("");
2534 String *terminator_code = NewString("");
2537 if (SwigType_type(Getattr(l, "type")) == T_VOID) {
2542 /* Attach the non-standard typemaps to the parameter list */
2543 Swig_typemap_attach_parms("cstype", l, NULL);
2544 Swig_typemap_attach_parms("csin", l, NULL);
2546 /* Get return types */
2547 if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
2548 String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
2551 substituteClassname(t, tm);
2552 Printf(return_type, "%s", tm);
2554 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
2557 /* Change function name for global variables */
2558 if (proxy_flag && global_variable_flag) {
2559 // Capitalize the first letter in the variable to create the getter/setter function name
2560 func_name = NewString("");
2561 setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(variable_name)) == 0);
2563 Printf(func_name, "set");
2565 Printf(func_name, "get");
2566 Putc(toupper((int) *Char(variable_name)), func_name);
2567 Printf(func_name, "%s", Char(variable_name) + 1);
2569 Swig_typemap_attach_parms("csvarin", l, NULL);
2571 func_name = Copy(Getattr(n, "sym:name"));
2574 /* Start generating the function */
2575 const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
2577 Printf(function_code, " %s\n", outattributes);
2578 const String *csattributes = Getattr(n, "feature:cs:attributes");
2580 Printf(function_code, " %s\n", csattributes);
2581 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2582 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2583 Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
2584 Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
2586 /* Get number of required and total arguments */
2587 num_arguments = emit_num_arguments(l);
2588 num_required = emit_num_required(l);
2590 bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
2593 /* Output each parameter */
2594 for (i = 0, p = l; i < num_arguments; i++) {
2596 /* Ignored parameters */
2597 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
2598 p = Getattr(p, "tmap:in:next");
2601 SwigType *pt = Getattr(p, "type");
2602 String *param_type = NewString("");
2605 /* Get the C# parameter type */
2606 if ((tm = Getattr(p, "tmap:cstype"))) {
2607 substituteClassname(pt, tm);
2608 const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
2609 Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
2611 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
2615 Printf(imcall, ", ");
2617 String *arg = makeParameterName(n, p, i, global_or_member_variable);
2619 // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2620 if ((tm = Getattr(p, "tmap:csin"))) {
2621 substituteClassname(pt, tm);
2622 Replaceall(tm, "$csinput", arg);
2623 String *pre = Getattr(p, "tmap:csin:pre");
2625 substituteClassname(pt, pre);
2626 Replaceall(pre, "$csinput", arg);
2627 if (Len(pre_code) > 0)
2628 Printf(pre_code, "\n");
2629 Printv(pre_code, pre, NIL);
2631 String *post = Getattr(p, "tmap:csin:post");
2633 substituteClassname(pt, post);
2634 Replaceall(post, "$csinput", arg);
2635 if (Len(post_code) > 0)
2636 Printf(post_code, "\n");
2637 Printv(post_code, post, NIL);
2639 String *terminator = Getattr(p, "tmap:csin:terminator");
2641 substituteClassname(pt, terminator);
2642 Replaceall(terminator, "$csinput", arg);
2643 if (Len(terminator_code) > 0)
2644 Insert(terminator_code, 0, "\n");
2645 Insert(terminator_code, 0, terminator);
2647 Printv(imcall, tm, NIL);
2649 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
2652 /* Add parameter to module class function */
2654 Printf(function_code, ", ");
2656 Printf(function_code, "%s %s", param_type, arg);
2658 p = Getattr(p, "tmap:in:next");
2663 Printf(imcall, ")");
2664 Printf(function_code, ")");
2666 // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in module class)
2667 if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
2668 excodeSubstitute(n, tm, "csout", n);
2669 bool is_pre_code = Len(pre_code) > 0;
2670 bool is_post_code = Len(post_code) > 0;
2671 bool is_terminator_code = Len(terminator_code) > 0;
2672 if (is_pre_code || is_post_code || is_terminator_code) {
2673 Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
2675 Insert(tm, 0, "\n try ");
2676 Printv(tm, " finally {\n", post_code, "\n }", NIL);
2678 Insert(tm, 0, "\n ");
2681 Insert(tm, 0, pre_code);
2682 Insert(tm, 0, "\n");
2684 if (is_terminator_code) {
2685 Printv(tm, "\n", terminator_code, NIL);
2690 if (GetFlag(n, "feature:new"))
2691 Replaceall(tm, "$owner", "true");
2693 Replaceall(tm, "$owner", "false");
2694 substituteClassname(t, tm);
2695 Replaceall(tm, "$imcall", imcall);
2697 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
2700 if (proxy_flag && global_variable_flag) {
2702 if (generate_property_declaration_flag) { // Ensure the declaration is generated just once should the property contain both a set and get
2703 // Get the C# variable type - obtained differently depending on whether a setter is required.
2704 String *variable_type = return_type;
2706 p = last_parm; // (last parameter is the only parameter for properties)
2707 SwigType *pt = Getattr(p, "type");
2708 if ((tm = Getattr(p, "tmap:cstype"))) {
2709 substituteClassname(pt, tm);
2710 String *cstypeout = Getattr(p, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
2711 variable_type = cstypeout ? cstypeout : tm;
2713 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2716 const String *csattributes = Getattr(n, "feature:cs:attributes");
2718 Printf(module_class_code, " %s\n", csattributes);
2719 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2721 methodmods = (is_public(n) ? public_string : protected_string);
2722 Printf(module_class_code, " %s static %s %s {", methodmods, variable_type, variable_name);
2724 generate_property_declaration_flag = false;
2728 p = last_parm; // (last parameter is the only parameter for properties)
2729 SwigType *pt = Getattr(p, "type");
2730 if ((tm = Getattr(p, "tmap:csvarin"))) {
2731 substituteClassname(pt, tm);
2732 Replaceall(tm, "$csinput", "value");
2733 Replaceall(tm, "$imcall", imcall);
2734 excodeSubstitute(n, tm, "csvarin", p);
2735 Printf(module_class_code, "%s", tm);
2737 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2741 if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
2742 if (GetFlag(n, "feature:new"))
2743 Replaceall(tm, "$owner", "true");
2745 Replaceall(tm, "$owner", "false");
2746 substituteClassname(t, tm);
2747 Replaceall(tm, "$imcall", imcall);
2748 excodeSubstitute(n, tm, "csvarout", n);
2749 Printf(module_class_code, "%s", tm);
2751 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
2755 // Normal function call
2756 Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2757 Printv(module_class_code, function_code, NIL);
2762 Delete(terminator_code);
2763 Delete(function_code);
2764 Delete(return_type);
2769 /*----------------------------------------------------------------------
2770 * replaceSpecialVariables()
2771 *--------------------------------------------------------------------*/
2773 virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
2775 SwigType *type = Getattr(parm, "type");
2776 substituteClassname(type, tm);
2779 /*----------------------------------------------------------------------
2780 * decodeEnumFeature()
2781 * Decode the possible enum features, which are one of:
2783 * %csenum(typeunsafe) - default
2786 *--------------------------------------------------------------------*/
2788 EnumFeature decodeEnumFeature(Node *n) {
2789 EnumFeature enum_feature = TypeunsafeEnum;
2790 String *feature = Getattr(n, "feature:cs:enum");
2792 if (Cmp(feature, "simple") == 0)
2793 enum_feature = SimpleEnum;
2794 else if (Cmp(feature, "typesafe") == 0)
2795 enum_feature = TypesafeEnum;
2796 else if (Cmp(feature, "proper") == 0)
2797 enum_feature = ProperEnum;
2799 return enum_feature;
2802 /* -----------------------------------------------------------------------
2804 * This method will return a string with an enum value to use in C# generated
2805 * code. If the %csconst feature is not used, the string will contain the intermediary
2806 * class call to obtain the enum value. The intermediary class and PINVOKE methods to obtain
2807 * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
2808 * is one and hopefully it will compile as C# code - e.g. 20 as in: enum E{e=20};
2809 * The %csconstvalue feature overrides all other ways to generate the constant value.
2810 * The caller must delete memory allocated for the returned string.
2811 * ------------------------------------------------------------------------ */
2813 String *enumValue(Node *n) {
2814 String *symname = Getattr(n, "sym:name");
2816 // Check for the %csconstvalue feature
2817 String *value = Getattr(n, "feature:cs:constvalue");
2820 // The %csconst feature determines how the constant value is obtained
2821 int const_feature_flag = GetFlag(n, "feature:cs:const");
2823 if (const_feature_flag) {
2824 // Use the C syntax to make a true C# constant and hope that it compiles as C# code
2825 value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
2827 // Get the enumvalue from a PINVOKE call
2828 if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
2829 // Strange hack to change the name
2830 Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
2832 value = NewStringf("%s.%s()", imclass_name, Swig_name_get(symname));
2834 memberconstantHandler(n);
2835 value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname)));
2842 /* -----------------------------------------------------------------------------
2844 * ----------------------------------------------------------------------------- */
2846 String *getEnumName(SwigType *t) {
2847 Node *enum_name = NULL;
2848 Node *n = enumLookup(t);
2850 String *symname = Getattr(n, "sym:name");
2852 // Add in class scope when referencing enum if not a global enum
2853 String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
2854 String *proxyname = 0;
2855 if (scopename_prefix) {
2856 proxyname = getProxyName(scopename_prefix);
2859 enum_name = NewStringf("%s.%s", proxyname, symname);
2861 enum_name = NewStringf("%s", symname);
2862 Delete(scopename_prefix);
2869 /* -----------------------------------------------------------------------------
2870 * substituteClassname()
2872 * Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
2873 * that SWIG knows about. Also substitutes enums with enum name.
2874 * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
2875 * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
2877 * pt - parameter type
2878 * tm - typemap contents that might contain the special variable to be replaced
2880 * tm - typemap contents complete with the special variable substitution
2882 * substitution_performed - flag indicating if a substitution was performed
2883 * ----------------------------------------------------------------------------- */
2885 bool substituteClassname(SwigType *pt, String *tm) {
2886 bool substitution_performed = false;
2887 SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
2888 SwigType *strippedtype = SwigType_strip_qualifiers(type);
2890 if (Strstr(tm, "$csclassname")) {
2891 SwigType *classnametype = Copy(strippedtype);
2892 substituteClassnameSpecialVariable(classnametype, tm, "$csclassname");
2893 substitution_performed = true;
2894 Delete(classnametype);
2896 if (Strstr(tm, "$*csclassname")) {
2897 SwigType *classnametype = Copy(strippedtype);
2898 Delete(SwigType_pop(classnametype));
2899 substituteClassnameSpecialVariable(classnametype, tm, "$*csclassname");
2900 substitution_performed = true;
2901 Delete(classnametype);
2903 if (Strstr(tm, "$&csclassname")) {
2904 SwigType *classnametype = Copy(strippedtype);
2905 SwigType_add_pointer(classnametype);
2906 substituteClassnameSpecialVariable(classnametype, tm, "$&csclassname");
2907 substitution_performed = true;
2908 Delete(classnametype);
2911 Delete(strippedtype);
2914 return substitution_performed;
2917 /* -----------------------------------------------------------------------------
2918 * substituteClassnameSpecialVariable()
2919 * ----------------------------------------------------------------------------- */
2921 void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
2922 if (SwigType_isenum(classnametype)) {
2923 String *enumname = getEnumName(classnametype);
2925 Replaceall(tm, classnamespecialvariable, enumname);
2927 Replaceall(tm, classnamespecialvariable, NewStringf("int"));
2929 String *classname = getProxyName(classnametype);
2931 Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too
2932 } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
2933 String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
2934 Replaceall(tm, classnamespecialvariable, descriptor);
2936 // Add to hash table so that the type wrapper classes can be created later
2937 Setattr(swig_types_hash, descriptor, classnametype);
2943 /* -----------------------------------------------------------------------------
2944 * makeParameterName()
2948 * p - parameter node
2949 * arg_num - parameter argument number
2950 * setter - set this flag when wrapping variables
2952 * arg - a unique parameter name
2953 * ----------------------------------------------------------------------------- */
2955 String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
2958 String *pn = Getattr(p, "name");
2960 // Use C parameter name unless it is a duplicate or an empty parameter name
2962 ParmList *plist = Getattr(n, "parms");
2964 if ((Cmp(pn, Getattr(plist, "name")) == 0))
2966 plist = nextSibling(plist);
2968 String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
2969 arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
2971 if (setter && Cmp(arg, "self") != 0) {
2972 // Note that in C# properties, the input variable name is always called 'value'
2974 arg = NewString("value");
2980 /* -----------------------------------------------------------------------------
2981 * emitTypeWrapperClass()
2982 * ----------------------------------------------------------------------------- */
2984 void emitTypeWrapperClass(String *classname, SwigType *type) {
2985 Node *n = NewHash();
2986 Setfile(n, input_file);
2987 Setline(n, line_number);
2989 String *swigtype = NewString("");
2990 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), classname);
2991 File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
2993 FileErrorDisplay(filen);
2994 SWIG_exit(EXIT_FAILURE);
2996 Append(filenames_list, Copy(filen));
3000 // Start writing out the type wrapper class file
3001 emitBanner(f_swigtype);
3003 addOpenNamespace(namespce, f_swigtype);
3005 // Pure C# baseclass and interfaces
3006 const String *pure_baseclass = typemapLookup(n, "csbase", type, WARN_NONE);
3007 const String *pure_interfaces = typemapLookup(n, "csinterfaces", type, WARN_NONE);
3010 Printv(swigtype, typemapLookup(n, "csimports", type, WARN_NONE), // Import statements
3014 const String *csattributes = typemapLookup(n, "csattributes", type, WARN_NONE);
3015 if (csattributes && *Char(csattributes))
3016 Printf(swigtype, "%s\n", csattributes);
3018 Printv(swigtype, typemapLookup(n, "csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
3019 " $csclassname", // Class name and base class
3020 (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
3021 ", " : "", pure_interfaces, " {", typemapLookup(n, "csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
3022 typemapLookup(n, "cscode", type, WARN_NONE), // extra C# code
3025 Replaceall(swigtype, "$csclassname", classname);
3026 Replaceall(swigtype, "$module", module_class_name);
3027 Replaceall(swigtype, "$imclassname", imclass_name);
3028 Replaceall(swigtype, "$dllimport", dllimport);
3030 Printv(f_swigtype, swigtype, NIL);
3032 addCloseNamespace(namespce, f_swigtype);
3039 /* -----------------------------------------------------------------------------
3041 * n - for input only and must contain info for Getfile(n) and Getline(n) to work
3042 * tmap_method - typemap method name
3043 * type - typemap type to lookup
3044 * warning - warning number to issue if no typemaps found
3045 * typemap_attributes - the typemap attributes are attached to this node and will
3046 * also be used for temporary storage if non null
3047 * return is never NULL, unlike Swig_typemap_lookup()
3048 * ----------------------------------------------------------------------------- */
3050 const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
3051 Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
3052 Setattr(node, "type", type);
3053 Setfile(node, Getfile(n));
3054 Setline(node, Getline(n));
3055 const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
3058 if (warning != WARN_NONE)
3059 Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
3061 if (!typemap_attributes)
3066 /* -----------------------------------------------------------------------------
3068 * Determine whether the code in the typemap can throw a C# exception.
3069 * If so, note it for later when excodeSubstitute() is called.
3070 * ----------------------------------------------------------------------------- */
3072 void canThrow(Node *n, const String *typemap, Node *parameter) {
3073 String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
3074 String *canthrow = Getattr(parameter, canthrow_attribute);
3076 Setattr(n, "csharp:canthrow", "1");
3077 Delete(canthrow_attribute);
3080 /* -----------------------------------------------------------------------------
3081 * excodeSubstitute()
3082 * If a method can throw a C# exception, additional exception code is added to
3083 * check for the pending exception so that it can then throw the exception. The
3084 * $excode special variable is replaced by the exception code in the excode
3085 * typemap attribute.
3086 * ----------------------------------------------------------------------------- */
3088 void excodeSubstitute(Node *n, String *code, const String *typemap, Node *parameter) {
3089 String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
3090 String *excode = Getattr(parameter, excode_attribute);
3091 if (Getattr(n, "csharp:canthrow")) {
3092 int count = Replaceall(code, "$excode", excode);
3093 if (count < 1 || !excode) {
3094 Swig_warning(WARN_CSHARP_EXCODE, input_file, line_number,
3095 "C# exception may not be thrown - no $excode or excode attribute in '%s' typemap.\n", typemap);
3098 Replaceall(code, "$excode", empty_string);
3100 Delete(excode_attribute);
3103 /* -----------------------------------------------------------------------------
3104 * addOpenNamespace()
3105 * ----------------------------------------------------------------------------- */
3107 void addOpenNamespace(String *namspace, File *file) {
3109 if (Len(namspace) > 0)
3110 Printf(file, "namespace %s {\n", namspace);
3113 /* -----------------------------------------------------------------------------
3114 * addCloseNamespace()
3115 * ----------------------------------------------------------------------------- */
3117 void addCloseNamespace(String *namspace, File *file) {
3119 if (Len(namspace) > 0)
3120 Printf(file, "\n}\n");
3123 /*----------------------------------------------------------------------
3124 * Start of director methods
3125 *--------------------------------------------------------------------*/
3128 /*----------------------------------------------------------------------
3129 * emitDirectorUpcalls()
3130 *--------------------------------------------------------------------*/
3132 void emitDirectorUpcalls() {
3134 Wrapper *w = NewWrapper();
3135 String *dmethod_data = NewString("");
3137 Iterator udata_iter;
3139 udata_iter = First(dmethods_seq);
3140 while (udata_iter.item) {
3141 UpcallData *udata = udata_iter.item;
3142 Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
3145 udata_iter = Next(udata_iter);
3147 if (udata_iter.item)
3148 Putc(',', dmethod_data);
3149 Putc('\n', dmethod_data);
3153 Wrapper_print(w, f_wrappers);
3154 Delete(dmethod_data);
3155 Delete(swig_module_init);
3161 /*----------------------------------------------------------------------
3162 * emitDirectorExtraMethods()
3164 * This is where the director connect method is
3166 *--------------------------------------------------------------------*/
3167 void emitDirectorExtraMethods(Node *n) {
3168 if (!Swig_directorclass(n))
3171 // Output the director connect method:
3172 String *norm_name = SwigType_namestr(Getattr(n, "name"));
3173 String *swig_director_connect = NewStringf("%s_director_connect", proxy_class_name);
3174 String *sym_name = Getattr(n, "sym:name");
3177 Printv(imclass_class_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", swig_director_connect, "\")]\n", NIL);
3178 Printf(imclass_class_code, " public static extern void %s(HandleRef jarg1", swig_director_connect);
3180 code_wrap = NewWrapper();
3181 Printf(code_wrap->def, "SWIGEXPORT void SWIGSTDCALL CSharp_%s(void *objarg", swig_director_connect);
3183 Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
3184 Printf(code_wrap->code, " SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
3185 // TODO: if statement not needed?? - Java too
3186 Printf(code_wrap->code, " if (director) {\n");
3187 Printf(code_wrap->code, " director->swig_connect_director(");
3189 for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
3190 UpcallData *udata = Getitem(dmethods_seq, i);
3191 String *methid = Getattr(udata, "class_methodidx");
3193 Printf(code_wrap->def, ", ");
3194 if (i != first_class_dmethod)
3195 Printf(code_wrap->code, ", ");
3196 Printf(code_wrap->def, "SwigDirector_%s::SWIG_Callback%s_t callback%s", sym_name, methid, methid);
3197 Printf(code_wrap->code, "callback%s", methid);
3198 Printf(imclass_class_code, ", %s.SwigDelegate%s_%s delegate%s", sym_name, sym_name, methid, methid);
3201 Printf(code_wrap->def, ") {\n");
3202 Printf(code_wrap->code, ");\n");
3203 Printf(imclass_class_code, ");\n");
3204 Printf(code_wrap->code, " }\n");
3205 Printf(code_wrap->code, "}\n");
3207 Wrapper_print(code_wrap, f_wrappers);
3208 DelWrapper(code_wrap);
3210 Delete(swig_director_connect);
3213 /* ---------------------------------------------------------------
3214 * classDirectorMethod()
3216 * Emit a virtual director method to pass a method call on to the
3217 * underlying Java object.
3219 * --------------------------------------------------------------- */
3221 int classDirectorMethod(Node *n, Node *parent, String *super) {
3222 String *empty_str = NewString("");
3223 String *classname = Getattr(parent, "sym:name");
3224 String *c_classname = Getattr(parent, "name");
3225 String *name = Getattr(n, "name");
3226 String *symname = Getattr(n, "sym:name");
3227 SwigType *type = Getattr(n, "type");
3228 SwigType *returntype = Getattr(n, "returntype");
3229 String *overloaded_name = getOverloadedName(n);
3230 String *storage = Getattr(n, "storage");
3231 String *value = Getattr(n, "value");
3232 String *decl = Getattr(n, "decl");
3233 String *declaration = NewString("");
3237 Wrapper *w = NewWrapper();
3238 ParmList *l = Getattr(n, "parms");
3239 bool is_void = !(Cmp(returntype, "void"));
3240 String *qualified_return = NewString("");
3241 bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
3242 int status = SWIG_OK;
3243 bool output_director = true;
3244 String *dirclassname = directorClassName(parent);
3245 String *qualified_name = NewStringf("%s::%s", dirclassname, name);
3246 SwigType *c_ret_type = NULL;
3247 String *jupcall_args = NewString("");
3248 String *imclass_dmethod;
3249 String *callback_typedef_parms = NewString("");
3250 String *delegate_parms = NewString("");
3251 String *proxy_method_types = NewString("");
3252 String *callback_def = NewString("");
3253 String *callback_code = NewString("");
3254 String *imcall_args = NewString("");
3256 bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
3258 // Kludge Alert: functionWrapper sets sym:overload properly, but it
3259 // isn't at this point, so we have to manufacture it ourselves. At least
3260 // we're consistent with the sym:overload name in functionWrapper. (?? when
3261 // does the overloaded method name get set?)
3263 imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(classname, overloaded_name));
3267 qualified_return = SwigType_rcaststr(returntype, "c_result");
3269 if (!is_void && !ignored_method) {
3270 if (!SwigType_isclass(returntype)) {
3271 if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
3272 String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
3273 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
3274 Delete(construct_result);
3276 String *base_typename = SwigType_base(returntype);
3277 String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
3278 Symtab *symtab = Getattr(n, "sym:symtab");
3279 Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
3281 if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstract"))) {
3282 /* initialize pointers to something sane. Same for abstract
3283 classes when a reference is returned. */
3284 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
3286 /* If returning a reference, initialize the pointer to a sane
3287 default - if a C# exception occurs, then the pointer returns
3288 something other than a NULL-initialized reference. */
3289 String *non_ref_type = Copy(returntype);
3291 /* Remove reference and const qualifiers */
3292 Replaceall(non_ref_type, "r.", "");
3293 Replaceall(non_ref_type, "q(const).", "");
3294 Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
3295 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
3297 Delete(non_ref_type);
3300 Delete(base_typename);
3301 Delete(resolved_typename);
3306 vt = cplus_value_type(returntype);
3308 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
3310 Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
3316 /* Create the intermediate class wrapper */
3317 Parm *tp = NewParmFromNode(returntype, empty_str, n);
3319 tm = Swig_typemap_lookup("imtype", tp, "", 0);
3321 String *imtypeout = Getattr(tp, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
3324 const String *im_directoroutattributes = Getattr(tp, "tmap:imtype:directoroutattributes");
3325 if (im_directoroutattributes) {
3326 Printf(callback_def, " %s\n", im_directoroutattributes);
3327 Printf(director_delegate_definitions, " %s\n", im_directoroutattributes);
3330 Printf(callback_def, " private %s SwigDirector%s(", tm, overloaded_name);
3331 if (!ignored_method)
3332 Printf(director_delegate_definitions, " public delegate %s", tm);
3334 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
3337 Parm *retpm = NewParmFromNode(returntype, empty_str, n);
3339 if ((c_ret_type = Swig_typemap_lookup("ctype", retpm, "", 0))) {
3341 if (!is_void && !ignored_method) {
3342 String *jretval_decl = NewStringf("%s jresult", c_ret_type);
3343 Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
3344 Delete(jretval_decl);
3347 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
3348 SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3349 output_director = false;
3355 /* Go through argument list, attach lnames for arguments */
3356 for (i = 0, p = l; p; p = nextSibling(p), ++i) {
3357 String *arg = Getattr(p, "name");
3358 String *lname = NewString("");
3360 if (!arg && Cmp(Getattr(p, "type"), "void")) {
3361 lname = NewStringf("arg%d", i);
3362 Setattr(p, "name", lname);
3366 Setattr(p, "lname", lname);
3369 /* Attach the standard typemaps */
3370 Swig_typemap_attach_parms("out", l, 0);
3371 Swig_typemap_attach_parms("ctype", l, 0);
3372 Swig_typemap_attach_parms("imtype", l, 0);
3373 Swig_typemap_attach_parms("cstype", l, 0);
3374 Swig_typemap_attach_parms("directorin", l, 0);
3375 Swig_typemap_attach_parms("csdirectorin", l, 0);
3378 if (!ignored_method)
3379 Printf(w->code, "if (!swig_callback%s) {\n", overloaded_name);
3381 if (!pure_virtual) {
3382 String *super_call = Swig_method_call(super, l);
3384 Printf(w->code, "%s;\n", super_call);
3385 if (!ignored_method)
3386 Printf(w->code, "return;\n");
3388 Printf(w->code, "return %s;\n", super_call);
3392 Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
3395 if (!ignored_method)
3396 Printf(w->code, "} else {\n");
3398 /* Go through argument list, convert from native to Java */
3399 for (p = l; p; /* empty */ ) {
3400 /* Is this superfluous? */
3401 while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
3402 p = Getattr(p, "tmap:directorin:next");
3405 SwigType *pt = Getattr(p, "type");
3406 String *ln = Copy(Getattr(p, "name"));
3407 String *c_param_type = NULL;
3408 String *c_decl = NewString("");
3409 String *arg = NewString("");
3411 Printf(arg, "j%s", ln);
3413 /* And add to the upcall args */
3415 Printf(jupcall_args, ", ");
3416 Printf(jupcall_args, "%s", arg);
3418 /* Get parameter's intermediary C type */
3419 if ((c_param_type = Getattr(p, "tmap:ctype"))) {
3420 String *ctypeout = Getattr(p, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
3422 c_param_type = ctypeout;
3424 Parm *tp = NewParmFromNode(c_param_type, empty_str, n);
3425 String *desc_tm = NULL;
3427 /* Add to local variables */
3428 Printf(c_decl, "%s %s", c_param_type, arg);
3429 if (!ignored_method)
3430 Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
3432 /* Add input marshalling code */
3433 if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
3434 && (tm = Getattr(p, "tmap:directorin"))) {
3436 Replaceall(tm, "$input", arg);
3437 Replaceall(tm, "$owner", "0");
3440 if (!ignored_method)
3441 Printf(w->code, "%s\n", tm);
3445 /* Add C type to callback typedef */
3447 Printf(callback_typedef_parms, ", ");
3448 Printf(callback_typedef_parms, "%s", c_param_type);
3450 /* Add parameter to the intermediate class code if generating the
3451 * intermediate's upcall code */
3452 if ((tm = Getattr(p, "tmap:imtype"))) {
3454 String *imtypeout = Getattr(p, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
3457 const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
3459 String *din = Copy(Getattr(p, "tmap:csdirectorin"));
3462 Replaceall(din, "$module", module_class_name);
3463 Replaceall(din, "$imclassname", imclass_name);
3464 substituteClassname(pt, din);
3465 Replaceall(din, "$iminput", ln);
3468 Printf(delegate_parms, ", ");
3469 Printf(proxy_method_types, ", ");
3470 Printf(imcall_args, ", ");
3472 Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
3475 Printv(imcall_args, din, NIL);
3477 Printv(imcall_args, ln, NIL);
3479 /* Get the C# parameter type */
3480 if ((tm = Getattr(p, "tmap:cstype"))) {
3481 substituteClassname(pt, tm);
3482 Printf(proxy_method_types, "typeof(%s)", tm);
3484 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
3487 Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, "No csdirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3488 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3489 output_director = false;
3492 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
3493 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3494 output_director = false;
3497 p = Getattr(p, "tmap:directorin:next");
3502 Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
3503 "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3504 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3507 Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
3508 "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
3509 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3513 output_director = false;
3518 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
3519 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3520 output_director = false;
3527 Delete(c_param_type);
3530 /* header declaration, start wrapper definition */
3532 SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
3533 target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
3534 Printf(w->def, "%s", target);
3535 Delete(qualified_name);
3537 target = Swig_method_decl(rtype, decl, name, l, 0, 1);
3538 Printf(declaration, " virtual %s", target);
3541 // Add any exception specifications to the methods in the director class
3542 ParmList *throw_parm_list = NULL;
3543 if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
3546 Append(w->def, " throw(");
3547 Append(declaration, " throw(");
3549 if (throw_parm_list)
3550 Swig_typemap_attach_parms("throws", throw_parm_list, 0);
3551 for (p = throw_parm_list; p; p = nextSibling(p)) {
3552 if ((tm = Getattr(p, "tmap:throws"))) {
3554 Append(w->def, ", ");
3555 Append(declaration, ", ");
3557 Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
3558 Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
3562 Append(w->def, ")");
3563 Append(declaration, ")");
3566 Append(w->def, " {");
3567 Append(declaration, ";\n");
3569 /* Finish off the inherited upcall's definition */
3571 Printf(callback_def, "%s)", delegate_parms);
3572 Printf(callback_def, " {\n");
3574 /* Emit the intermediate class's upcall to the actual class */
3576 String *upcall = NewStringf("%s(%s)", symname, imcall_args);
3579 Parm *tp = NewParmFromNode(returntype, empty_str, n);
3581 if ((tm = Swig_typemap_lookup("csdirectorout", tp, "", 0))) {
3582 substituteClassname(returntype, tm);
3583 Replaceall(tm, "$cscall", upcall);
3585 Printf(callback_code, " return %s;\n", tm);
3591 Printf(callback_code, " %s;\n", upcall);
3593 Printf(callback_code, " }\n");
3596 if (!ignored_method) {
3598 Printf(w->code, "jresult = (%s) ", c_ret_type);
3600 Printf(w->code, "swig_callback%s(%s);\n", overloaded_name, jupcall_args);
3603 String *jresult_str = NewString("jresult");
3604 String *result_str = NewString("c_result");
3605 Parm *tp = NewParmFromNode(returntype, result_str, n);
3607 /* Copy jresult into c_result... */
3608 if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) {
3609 Replaceall(tm, "$input", jresult_str);
3610 Replaceall(tm, "$result", result_str);
3611 Printf(w->code, "%s\n", tm);
3613 Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
3614 "Unable to use return type %s used in %s::%s (skipping director method)\n",
3615 SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3616 output_director = false;
3620 Delete(jresult_str);
3624 /* Terminate wrapper code */
3625 Printf(w->code, "}\n");
3627 Printf(w->code, "return %s;", qualified_return);
3630 Printf(w->code, "}");
3632 // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
3633 String *inline_extra_method = NewString("");
3634 if (dirprot_mode() && !is_public(n) && !pure_virtual) {
3635 Printv(inline_extra_method, declaration, NIL);
3636 String *extra_method_name = NewStringf("%sSwigPublic", name);
3637 Replaceall(inline_extra_method, name, extra_method_name);
3638 Replaceall(inline_extra_method, ";\n", " {\n ");
3640 Printf(inline_extra_method, "return ");
3641 String *methodcall = Swig_method_call(super, l);
3642 Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
3644 Delete(extra_method_name);
3648 if (status == SWIG_OK && output_director) {
3650 Replaceall(w->code, "$null", qualified_return);
3652 Replaceall(w->code, "$null", "");
3654 if (!ignored_method)
3655 Printv(director_delegate_callback, "\n", callback_def, callback_code, NIL);
3656 if (!Getattr(n, "defaultargs")) {
3657 Wrapper_print(w, f_directors);
3658 Printv(f_directors_h, declaration, NIL);
3659 Printv(f_directors_h, inline_extra_method, NIL);
3663 if (!ignored_method) {
3664 /* Emit the actual upcall through */
3665 UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name);
3666 String *methid = Getattr(udata, "class_methodidx");
3668 Printf(director_callback_typedefs, " typedef %s (SWIGSTDCALL* SWIG_Callback%s_t)(", c_ret_type, methid);
3669 Printf(director_callback_typedefs, "%s);\n", callback_typedef_parms);
3670 Printf(director_callbacks, " SWIG_Callback%s_t swig_callback%s;\n", methid, overloaded_name);
3672 Printf(director_delegate_definitions, " SwigDelegate%s_%s(%s);\n", classname, methid, delegate_parms);
3673 Printf(director_delegate_instances, " private SwigDelegate%s_%s swigDelegate%s;\n", classname, methid, methid);
3674 Printf(director_method_types, " private static Type[] swigMethodTypes%s = new Type[] { %s };\n", methid, proxy_method_types);
3675 Printf(director_connect_parms, "SwigDirector%s%s delegate%s", classname, methid, methid);
3678 Delete(qualified_return);
3680 Delete(declaration);
3681 Delete(callback_typedef_parms);
3682 Delete(delegate_parms);
3683 Delete(proxy_method_types);
3684 Delete(callback_def);
3685 Delete(callback_code);
3691 /* ------------------------------------------------------------
3692 * classDirectorConstructor()
3693 * ------------------------------------------------------------ */
3695 int classDirectorConstructor(Node *n) {
3696 Node *parent = parentNode(n);
3697 String *decl = Getattr(n, "decl");;
3698 String *supername = Swig_class_name(parent);
3699 String *classname = directorClassName(parent);
3700 String *sub = NewString("");
3702 ParmList *superparms = Getattr(n, "parms");
3706 /* Assign arguments to superclass's parameters, if not already done */
3707 for (p = superparms; p; p = nextSibling(p)) {
3708 String *pname = Getattr(p, "name");
3711 pname = NewStringf("arg%d", argidx++);
3712 Setattr(p, "name", pname);
3716 // TODO: Is this copy needed?
3717 parms = CopyParmList(superparms);
3719 if (!Getattr(n, "defaultargs")) {
3722 String *basetype = Getattr(parent, "classtype");
3723 String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
3724 String *call = Swig_csuperclass_call(0, basetype, superparms);
3725 String *classtype = SwigType_namestr(Getattr(n, "name"));
3727 Printf(f_directors, "%s::%s : %s, %s {\n", classname, target, call, Getattr(parent, "director:ctor"));
3728 Printf(f_directors, " swig_init_callbacks();\n");
3729 Printf(f_directors, "}\n\n");
3736 /* constructor header */
3738 String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
3739 Printf(f_directors_h, " %s;\n", target);
3747 return Language::classDirectorConstructor(n);
3750 /* ------------------------------------------------------------
3751 * classDirectorDefaultConstructor()
3752 * ------------------------------------------------------------ */
3754 int classDirectorDefaultConstructor(Node *n) {
3755 String *classname = Swig_class_name(n);
3756 String *classtype = SwigType_namestr(Getattr(n, "name"));
3757 Wrapper *w = NewWrapper();
3759 Printf(w->def, "SwigDirector_%s::SwigDirector_%s() : %s {", classname, classname, Getattr(n, "director:ctor"));
3760 Printf(w->code, "}\n");
3761 Wrapper_print(w, f_directors);
3763 Printf(f_directors_h, " SwigDirector_%s();\n", classname);
3767 return Language::classDirectorDefaultConstructor(n);
3771 /* ------------------------------------------------------------
3772 * classDirectorInit()
3773 * ------------------------------------------------------------ */
3775 int classDirectorInit(Node *n) {
3776 Delete(none_comparison);
3777 none_comparison = NewString(""); // not used
3779 Delete(director_ctor_code);
3780 director_ctor_code = NewString("$director_new");
3782 Java_director_declaration(n);
3784 Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
3785 Printf(f_directors_h, "\npublic:\n");
3787 /* Keep track of the director methods for this class */
3788 first_class_dmethod = curr_class_dmethod = n_dmethods;
3790 director_callback_typedefs = NewString("");
3791 director_callbacks = NewString("");
3792 director_delegate_callback = NewString("");
3793 director_delegate_definitions = NewString("");
3794 director_delegate_instances = NewString("");
3795 director_method_types = NewString("");
3796 director_connect_parms = NewString("");
3798 return Language::classDirectorInit(n);
3801 /* ----------------------------------------------------------------------
3802 * classDirectorDestructor()
3803 * ---------------------------------------------------------------------- */
3805 int classDirectorDestructor(Node *n) {
3806 Node *current_class = getCurrentClass();
3807 String *full_classname = Getattr(current_class, "name");
3808 String *classname = Swig_class_name(current_class);
3809 Wrapper *w = NewWrapper();
3811 if (Getattr(n, "throw")) {
3812 Printf(f_directors_h, " virtual ~SwigDirector_%s() throw ();\n", classname);
3813 Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() throw () {\n", classname, classname);
3815 Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname);
3816 Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname);
3819 /* Ensure that correct directordisconnect typemap's method name is called
3822 const String *disconn_tm = NULL;
3823 Node *disconn_attr = NewHash();
3824 String *disconn_methodname = NULL;
3826 disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
3827 disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
3829 Printv(w->code, "}\n", NIL);
3831 Wrapper_print(w, f_directors);
3834 Delete(disconn_attr);
3839 /* ------------------------------------------------------------
3840 * classDirectorEnd()
3841 * ------------------------------------------------------------ */
3843 int classDirectorEnd(Node *n) {
3845 String *director_classname = directorClassName(n);
3847 Wrapper *w = NewWrapper();
3849 if (Len(director_callback_typedefs) > 0) {
3850 Printf(f_directors_h, "\n%s", director_callback_typedefs);
3853 Printf(f_directors_h, " void swig_connect_director(");
3855 Printf(w->def, "void %s::swig_connect_director(", director_classname);
3857 for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
3858 UpcallData *udata = Getitem(dmethods_seq, i);
3859 String *methid = Getattr(udata, "class_methodidx");
3860 String *overname = Getattr(udata, "overname");
3862 Printf(f_directors_h, "SWIG_Callback%s_t callback%s", methid, overname);
3863 Printf(w->def, "SWIG_Callback%s_t callback%s", methid, overname);
3864 Printf(w->code, "swig_callback%s = callback%s;\n", overname, overname);
3865 if (i != curr_class_dmethod - 1) {
3866 Printf(f_directors_h, ", ");
3867 Printf(w->def, ", ");
3871 Printf(f_directors_h, ");\n");
3872 Printf(w->def, ") {");
3875 if (Len(director_callback_typedefs) > 0) {
3876 Printf(f_directors_h, "\nprivate:\n%s", director_callbacks);
3878 Printf(f_directors_h, " void swig_init_callbacks();\n");
3879 Printf(f_directors_h, "};\n\n");
3880 Printf(w->code, "}\n\n");
3882 Printf(w->code, "void %s::swig_init_callbacks() {\n", director_classname);
3883 for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
3884 UpcallData *udata = Getitem(dmethods_seq, i);
3885 String *overname = Getattr(udata, "overname");
3886 Printf(w->code, "swig_callback%s = 0;\n", overname);
3888 Printf(w->code, "}");
3890 Wrapper_print(w, f_directors);
3894 return Language::classDirectorEnd(n);
3897 /* --------------------------------------------------------------------
3898 * classDirectorDisown()
3899 * ------------------------------------------------------------------*/
3900 virtual int classDirectorDisown(Node *n) {
3905 /*----------------------------------------------------------------------
3906 * extraDirectorProtectedCPPMethodsRequired()
3907 *--------------------------------------------------------------------*/
3909 bool extraDirectorProtectedCPPMethodsRequired() const {
3913 /*----------------------------------------------------------------------
3914 * Java_director_declaration()
3916 * Generate the director class's declaration
3917 * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
3918 *--------------------------------------------------------------------*/
3920 void Java_director_declaration(Node *n) {
3922 String *base = Getattr(n, "classtype");
3923 String *class_ctor = NewString("Swig::Director()");
3925 String *classname = Swig_class_name(n);
3926 String *directorname = NewStringf("SwigDirector_%s", classname);
3927 String *declaration = Swig_class_declaration(n, directorname);
3929 Printf(declaration, " : public %s, public Swig::Director", base);
3931 // Stash stuff for later.
3932 Setattr(n, "director:decl", declaration);
3933 Setattr(n, "director:ctor", class_ctor);
3936 }; /* class CSHARP */
3938 /* -----------------------------------------------------------------------------
3939 * swig_csharp() - Instantiate module
3940 * ----------------------------------------------------------------------------- */
3942 static Language *new_swig_csharp() {
3943 return new CSHARP();
3945 extern "C" Language *swig_csharp(void) {
3946 return new_swig_csharp();
3949 /* -----------------------------------------------------------------------------
3950 * Static member variables
3951 * ----------------------------------------------------------------------------- */
3953 const char *CSHARP::usage = (char *) "\
3954 C# Options (available with -csharp)\n\
3955 -dllimport <dl> - Override DllImport attribute name to <dl>\n\
3956 -namespace <nm> - Generate wrappers into C# namespace <nm>\n\
3957 -noproxy - Generate the low-level functional interface instead\n\
3959 -oldvarnames - old intermediary method names for variable wrappers\n\