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. 4 * 5 * csharp.cxx 6 * 7 * C# language module for SWIG. 8 * ----------------------------------------------------------------------------- */ 9 10char cvsroot_csharp_cxx[] = "$Id: csharp.cxx 11583 2009-08-15 23:22:20Z wsfulton $"; 11 12#include "swigmod.h" 13#include <limits.h> // for INT_MAX 14#include "cparse.h" 15#include <ctype.h> 16 17/* Hash type used for upcalls from C/C++ */ 18typedef DOH UpcallData; 19 20class CSHARP:public Language { 21 static const char *usage; 22 const String *empty_string; 23 const String *public_string; 24 const String *protected_string; 25 26 Hash *swig_types_hash; 27 File *f_begin; 28 File *f_runtime; 29 File *f_runtime_h; 30 File *f_header; 31 File *f_wrappers; 32 File *f_init; 33 File *f_directors; 34 File *f_directors_h; 35 List *filenames_list; 36 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 46 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; 57 String *enum_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 78 79 // Director method stuff: 80 List *dmethods_seq; 81 Hash *dmethods_table; 82 int n_dmethods; 83 int n_directors; 84 int first_class_dmethod; 85 int curr_class_dmethod; 86 87 enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum }; 88 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)); 93 return p; 94 } 95 96public: 97 98 /* ----------------------------------------------------------------------------- 99 * CSHARP() 100 * ----------------------------------------------------------------------------- */ 101 102 CSHARP():empty_string(NewString("")), 103 public_string(NewString("public")), 104 protected_string(NewString("protected")), 105 swig_types_hash(NULL), 106 f_begin(NULL), 107 f_runtime(NULL), 108 f_runtime_h(NULL), 109 f_header(NULL), 110 f_wrappers(NULL), 111 f_init(NULL), 112 f_directors(NULL), 113 f_directors_h(NULL), 114 filenames_list(NULL), 115 proxy_flag(true), 116 native_function_flag(false), 117 enum_constant_flag(false), 118 static_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), 124 imclass_name(NULL), 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), 131 variable_name(NULL), 132 proxy_class_constants_code(NULL), 133 module_class_constants_code(NULL), 134 enum_code(NULL), 135 dllimport(NULL), 136 namespce(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), 145 upcasts_code(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), 155 dmethods_seq(NULL), 156 dmethods_table(NULL), 157 n_dmethods(0), 158 n_directors(0) { 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; 163 } 164 165 /* ----------------------------------------------------------------------------- 166 * getProxyName() 167 * 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 * ----------------------------------------------------------------------------- */ 171 172 String *getProxyName(SwigType *t) { 173 if (proxy_flag) { 174 Node *n = classLookup(t); 175 if (n) { 176 return Getattr(n, "sym:name"); 177 } 178 } 179 return NULL; 180 } 181 182 /* ----------------------------------------------------------------------------- 183 * directorClassName() 184 * ----------------------------------------------------------------------------- */ 185 186 String *directorClassName(Node *n) { 187 String *dirclassname; 188 const char *attrib = "director:classname"; 189 190 if (!(dirclassname = Getattr(n, attrib))) { 191 String *classname = Getattr(n, "sym:name"); 192 193 dirclassname = NewStringf("SwigDirector_%s", classname); 194 Setattr(n, attrib, dirclassname); 195 } 196 197 return dirclassname; 198 } 199 200 /* ------------------------------------------------------------ 201 * main() 202 * ------------------------------------------------------------ */ 203 204 virtual void main(int argc, char *argv[]) { 205 206 SWIG_library_directory("csharp"); 207 208 // Look for certain command line options 209 for (int i = 1; i < argc; i++) { 210 if (argv[i]) { 211 if (strcmp(argv[i], "-dllimport") == 0) { 212 if (argv[i + 1]) { 213 dllimport = NewString(""); 214 Printf(dllimport, argv[i + 1]); 215 Swig_mark_arg(i); 216 Swig_mark_arg(i + 1); 217 i++; 218 } else { 219 Swig_arg_error(); 220 } 221 } else if (strcmp(argv[i], "-namespace") == 0) { 222 if (argv[i + 1]) { 223 namespce = NewString(""); 224 Printf(namespce, argv[i + 1]); 225 Swig_mark_arg(i); 226 Swig_mark_arg(i + 1); 227 i++; 228 } else { 229 Swig_arg_error(); 230 } 231 } else if ((strcmp(argv[i], "-noproxy") == 0)) { 232 Swig_mark_arg(i); 233 proxy_flag = false; 234 } else if (strcmp(argv[i], "-oldvarnames") == 0) { 235 Swig_mark_arg(i); 236 old_variable_names = true; 237 } else if (strcmp(argv[i], "-help") == 0) { 238 Printf(stdout, "%s\n", usage); 239 } 240 } 241 } 242 243 // Add a symbol to the parser for conditional compilation 244 Preprocessor_define("SWIGCSHARP 1", 0); 245 246 // Add typemap definitions 247 SWIG_typemap_lang("csharp"); 248 SWIG_config_file("csharp.swg"); 249 250 allow_overloading(); 251 } 252 253 /* --------------------------------------------------------------------- 254 * top() 255 * --------------------------------------------------------------------- */ 256 257 virtual int top(Node *n) { 258 259 // Get any options set in the module directive 260 Node *optionsnode = Getattr(Getattr(n, "module"), "options"); 261 262 if (optionsnode) { 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. 269 * 270 * use %module(directors="1") modulename at the start of the 271 * interface file to enable director generation. 272 */ 273 if (Getattr(optionsnode, "directors")) { 274 allow_directors(); 275 } 276 if (Getattr(optionsnode, "dirprot")) { 277 allow_dirprot(); 278 } 279 allow_allprotected(GetFlag(optionsnode, "allprotected")); 280 } 281 282 /* Initialize all of the output files */ 283 String *outfile = Getattr(n, "outfile"); 284 String *outfile_h = Getattr(n, "outfile_h"); 285 286 if (!outfile) { 287 Printf(stderr, "Unable to determine outfile\n"); 288 SWIG_exit(EXIT_FAILURE); 289 } 290 291 f_begin = NewFile(outfile, "w", SWIG_output_files()); 292 if (!f_begin) { 293 FileErrorDisplay(outfile); 294 SWIG_exit(EXIT_FAILURE); 295 } 296 297 if (directorsEnabled()) { 298 if (!outfile_h) { 299 Printf(stderr, "Unable to determine outfile_h\n"); 300 SWIG_exit(EXIT_FAILURE); 301 } 302 f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files()); 303 if (!f_runtime_h) { 304 FileErrorDisplay(outfile_h); 305 SWIG_exit(EXIT_FAILURE); 306 } 307 } 308 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(""); 315 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); 324 325 swig_types_hash = NewHash(); 326 filenames_list = NewList(); 327 328 // Make the intermediary class and module class names. The intermediary class name can be set in the module directive. 329 if (!imclass_name) { 330 imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name")); 331 module_class_name = Copy(Getattr(n, "name")); 332 } else { 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")); 336 else 337 module_class_name = Copy(Getattr(n, "name")); 338 } 339 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(); 358 n_dmethods = 0; 359 n_directors = 0; 360 if (!namespce) 361 namespce = NewString(""); 362 if (!dllimport) 363 dllimport = Copy(module_class_name); 364 365 Swig_banner(f_begin); 366 367 Printf(f_runtime, "\n"); 368 Printf(f_runtime, "#define SWIGCSHARP\n"); 369 370 if (directorsEnabled()) { 371 Printf(f_runtime, "#define SWIG_DIRECTORS\n"); 372 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); 378 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"); 383 if (outfile_h) 384 Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h)); 385 } 386 387 Printf(f_runtime, "\n"); 388 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"); 393 } 394 395 Printf(f_wrappers, "\n#ifdef __cplusplus\n"); 396 Printf(f_wrappers, "extern \"C\" {\n"); 397 Printf(f_wrappers, "#endif\n\n"); 398 399 /* Emit code */ 400 Language::top(n); 401 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); 405 } 406 // Generate the intermediary class 407 { 408 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name); 409 File *f_im = NewFile(filen, "w", SWIG_output_files()); 410 if (!f_im) { 411 FileErrorDisplay(filen); 412 SWIG_exit(EXIT_FAILURE); 413 } 414 Append(filenames_list, Copy(filen)); 415 Delete(filen); 416 filen = NULL; 417 418 // Start writing out the intermediary class file 419 emitBanner(f_im); 420 421 addOpenNamespace(namespce, f_im); 422 423 if (imclass_imports) 424 Printf(f_im, "%s\n", imclass_imports); 425 426 if (Len(imclass_class_modifiers) > 0) 427 Printf(f_im, "%s ", imclass_class_modifiers); 428 Printf(f_im, "%s ", imclass_name); 429 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); 434 Printf(f_im, "{\n"); 435 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); 442 443 // Finish off the class 444 Printf(f_im, "}\n"); 445 addCloseNamespace(namespce, f_im); 446 447 Close(f_im); 448 } 449 450 // Generate the C# module class 451 { 452 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name); 453 File *f_module = NewFile(filen, "w", SWIG_output_files()); 454 if (!f_module) { 455 FileErrorDisplay(filen); 456 SWIG_exit(EXIT_FAILURE); 457 } 458 Append(filenames_list, Copy(filen)); 459 Delete(filen); 460 filen = NULL; 461 462 // Start writing out the module class file 463 emitBanner(f_module); 464 465 addOpenNamespace(namespce, f_module); 466 467 if (module_imports) 468 Printf(f_module, "%s\n", module_imports); 469 470 if (Len(module_class_modifiers) > 0) 471 Printf(f_module, "%s ", module_class_modifiers); 472 Printf(f_module, "%s ", module_class_name); 473 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"); 479 480 Replaceall(module_class_code, "$module", module_class_name); 481 Replaceall(module_class_constants_code, "$module", module_class_name); 482 483 Replaceall(module_class_code, "$imclassname", imclass_name); 484 Replaceall(module_class_constants_code, "$imclassname", imclass_name); 485 486 Replaceall(module_class_code, "$dllimport", dllimport); 487 Replaceall(module_class_constants_code, "$dllimport", dllimport); 488 489 // Add the wrapper methods 490 Printv(f_module, module_class_code, NIL); 491 492 // Write out all the global constants 493 Printv(f_module, module_class_constants_code, NIL); 494 495 // Finish off the class 496 Printf(f_module, "}\n"); 497 addCloseNamespace(namespce, f_module); 498 499 Close(f_module); 500 } 501 502 if (upcasts_code) 503 Printv(f_wrappers, upcasts_code, NIL); 504 505 Printf(f_wrappers, "#ifdef __cplusplus\n"); 506 Printf(f_wrappers, "}\n"); 507 Printf(f_wrappers, "#endif\n"); 508 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); 512 } 513 514 // Check for overwriting file problems on filesystems that are case insensitive 515 Iterator it1; 516 Iterator it2; 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); 526 } 527 } 528 Delete(item2_lower); 529 } 530 Delete(item1_lower); 531 } 532 533 Delete(swig_types_hash); 534 swig_types_hash = NULL; 535 Delete(filenames_list); 536 filenames_list = NULL; 537 Delete(imclass_name); 538 imclass_name = NULL; 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); 570 upcasts_code = NULL; 571 Delete(dmethods_seq); 572 dmethods_seq = NULL; 573 Delete(dmethods_table); 574 dmethods_table = NULL; 575 Delete(namespce); 576 namespce = NULL; 577 n_dmethods = 0; 578 579 /* Close all of the files */ 580 Dump(f_runtime, f_begin); 581 Dump(f_header, f_begin); 582 583 if (directorsEnabled()) { 584 Dump(f_directors, f_begin); 585 Dump(f_directors_h, f_runtime_h); 586 587 Printf(f_runtime_h, "\n"); 588 Printf(f_runtime_h, "#endif\n"); 589 590 Close(f_runtime_h); 591 Delete(f_runtime_h); 592 f_runtime_h = NULL; 593 Delete(f_directors); 594 f_directors = NULL; 595 Delete(f_directors_h); 596 f_directors_h = NULL; 597 } 598 599 Dump(f_wrappers, f_begin); 600 Wrapper_pretty_print(f_init, f_begin); 601 Delete(f_header); 602 Delete(f_wrappers); 603 Delete(f_init); 604 Close(f_begin); 605 Delete(f_runtime); 606 Delete(f_begin); 607 return SWIG_OK; 608 } 609 610 /* ----------------------------------------------------------------------------- 611 * emitBanner() 612 * ----------------------------------------------------------------------------- */ 613 614 void emitBanner(File *f) { 615 Printf(f, "/* ----------------------------------------------------------------------------\n"); 616 Swig_banner_target_lang(f, " *"); 617 Printf(f, " * ----------------------------------------------------------------------------- */\n\n"); 618 } 619 620 /*----------------------------------------------------------------------- 621 * Add new director upcall signature 622 *----------------------------------------------------------------------*/ 623 624 UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) { 625 UpcallData *udata; 626 String *imclass_methodidx; 627 String *class_methodidx; 628 Hash *new_udata; 629 String *key = NewStringf("%s|%s", imclass_method, decl); 630 631 ++curr_class_dmethod; 632 633 /* Do we know about this director class already? */ 634 if ((udata = Getattr(dmethods_table, key))) { 635 Delete(key); 636 return Getattr(udata, "methodoff"); 637 } 638 639 imclass_methodidx = NewStringf("%d", n_dmethods); 640 class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod); 641 n_dmethods++; 642 643 new_udata = NewHash(); 644 Append(dmethods_seq, new_udata); 645 Setattr(dmethods_table, key, new_udata); 646 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)); 655 656 Delete(key); 657 return new_udata; 658 } 659 660 /*----------------------------------------------------------------------- 661 * Get director upcall signature 662 *----------------------------------------------------------------------*/ 663 664 /* 665 UpcallData * getUpcallMethodData(String *director_class, String *decl) { 666 String *key = NewStringf("%s|%s", director_class, decl); 667 UpcallData *udata = Getattr(dmethods_table, key); 668 669 Delete(key); 670 return udata; 671 } 672 */ 673 674 /* ---------------------------------------------------------------------- 675 * nativeWrapper() 676 * ---------------------------------------------------------------------- */ 677 678 virtual int nativeWrapper(Node *n) { 679 String *wrapname = Getattr(n, "wrap:name"); 680 681 if (!addSymbol(wrapname, n)) 682 return SWIG_ERROR; 683 684 if (Getattr(n, "type")) { 685 Swig_save("nativeWrapper", n, "name", NIL); 686 Setattr(n, "name", wrapname); 687 native_function_flag = true; 688 functionWrapper(n); 689 Swig_restore(n); 690 native_function_flag = false; 691 } else { 692 Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n, "wrap:name")); 693 } 694 695 return SWIG_OK; 696 } 697 698 /* ---------------------------------------------------------------------- 699 * functionWrapper() 700 * ---------------------------------------------------------------------- */ 701 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"); 706 String *tm; 707 Parm *p; 708 int i; 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; 717 bool is_void_return; 718 String *overloaded_name = getOverloadedName(n); 719 720 if (!Getattr(n, "sym:overloaded")) { 721 if (!addSymbol(Getattr(n, "sym:name"), n)) 722 return SWIG_ERROR; 723 } 724 725 /* 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. 729 */ 730 731 // A new wrapper function object 732 Wrapper *f = NewWrapper(); 733 734 // Make a wrapper name for this function 735 String *wname = Swig_name_wrapper(overloaded_name); 736 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); 740 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 744 if (ctypeout) 745 tm = ctypeout; 746 Printf(c_return_type, "%s", tm); 747 } else { 748 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t, 0)); 749 } 750 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 753 if (imtypeout) 754 tm = imtypeout; 755 Printf(im_return_type, "%s", tm); 756 im_outattributes = Getattr(n, "tmap:imtype:outattributes"); 757 } else { 758 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0)); 759 } 760 761 is_void_return = (Cmp(c_return_type, "void") == 0); 762 if (!is_void_return) 763 Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL); 764 765 Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL); 766 767 // Emit all of the local variables for holding arguments. 768 emit_parameter_variables(l, f); 769 770 /* Attach the standard typemaps */ 771 emit_attach_parmmaps(l, f); 772 773 // Parameter overloading 774 Setattr(n, "wrap:parms", l); 775 Setattr(n, "wrap:name", wname); 776 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")) 782 return SWIG_OK; 783 } 784 785 Printv(imclass_class_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", overloaded_name, "\")]\n", NIL); 786 787 if (im_outattributes) 788 Printf(imclass_class_code, " %s\n", im_outattributes); 789 790 Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name); 791 792 793 /* Get number of required and total arguments */ 794 num_arguments = emit_num_arguments(l); 795 num_required = emit_num_required(l); 796 int gencomma = 0; 797 798 // Now walk the function parameter list and generate code to get arguments 799 for (i = 0, p = l; i < num_arguments; i++) { 800 801 while (checkAttribute(p, "tmap:in:numinputs", "0")) { 802 p = Getattr(p, "tmap:in:next"); 803 } 804 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(""); 810 811 Printf(arg, "j%s", ln); 812 813 /* Get the ctype types of the parameter */ 814 if ((tm = Getattr(p, "tmap:ctype"))) { 815 Printv(c_param_type, tm, NIL); 816 } else { 817 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0)); 818 } 819 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); 824 } else { 825 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0)); 826 } 827 828 /* Add parameter to intermediary class method */ 829 if (gencomma) 830 Printf(imclass_class_code, ", "); 831 Printf(imclass_class_code, "%s %s", im_param_type, arg); 832 833 // Add parameter to C function 834 Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL); 835 836 gencomma = 1; 837 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"); 848 } else { 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)); 850 p = nextSibling(p); 851 } 852 Delete(im_param_type); 853 Delete(c_param_type); 854 Delete(arg); 855 } 856 857 /* Insert constraint checking code */ 858 for (p = l; p;) { 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"); 866 } else { 867 p = nextSibling(p); 868 } 869 } 870 871 /* Insert cleanup code */ 872 for (p = l; p;) { 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"); 880 } else { 881 p = nextSibling(p); 882 } 883 } 884 885 /* Insert argument output code */ 886 for (p = l; p;) { 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"); 896 } else { 897 p = nextSibling(p); 898 } 899 } 900 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); 908 } 909 } 910 } 911 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); 918 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"))); 922 } 923 924 Swig_director_emit_dynamic_cast(n, f); 925 String *actioncode = emit_action(n); 926 927 if (Cmp(nodeType(n), "constant") == 0) 928 Swig_restore(n); 929 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"); 936 937 if (GetFlag(n, "feature:new")) 938 Replaceall(tm, "$owner", "1"); 939 else 940 Replaceall(tm, "$owner", "0"); 941 942 Printf(f->code, "%s", tm); 943 null_attribute = Getattr(n, "tmap:out:null"); 944 if (Len(tm)) 945 Printf(f->code, "\n"); 946 } else { 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")); 948 } 949 emit_return_variable(n, t, f); 950 } 951 952 /* Output argument output code */ 953 Printv(f->code, outarg, NIL); 954 955 /* Output cleanup code */ 956 Printv(f->code, cleanup, NIL); 957 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); 964 } 965 } 966 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); 973 } 974 } 975 976 /* Finish C function and intermediary class function definitions */ 977 Printf(imclass_class_code, ")"); 978 Printf(imclass_class_code, ";\n"); 979 980 Printf(f->def, ") {"); 981 982 if (!is_void_return) 983 Printv(f->code, " return jresult;\n", NIL); 984 Printf(f->code, "}\n"); 985 986 /* Substitute the cleanup code */ 987 Replaceall(f->code, "$cleanup", cleanup); 988 989 /* Substitute the function name */ 990 Replaceall(f->code, "$symname", symname); 991 992 /* Contract macro modification */ 993 if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) { 994 Setattr(n, "csharp:canthrow", "1"); 995 } 996 997 if (!null_attribute) 998 Replaceall(f->code, "$null", "0"); 999 else 1000 Replaceall(f->code, "$null", null_attribute); 1001 1002 /* Dump the function out */ 1003 if (!native_function_flag) { 1004 Wrapper_print(f, f_wrappers); 1005 1006 // Handle %csexception which sets the canthrow attribute 1007 if (Getattr(n, "feature:except:canthrow")) 1008 Setattr(n, "csharp:canthrow", "1"); 1009 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"); 1021 } 1022 } 1023 } 1024 1025 if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) { 1026 moduleClassFunctionHandler(n); 1027 } 1028 1029 /* 1030 * Generate the proxy class properties for public member variables. 1031 * Not for enums and constants. 1032 */ 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; 1036 1037 String *getter_setter_name = NewString(""); 1038 if (!getter_flag) 1039 Printf(getter_setter_name, "set"); 1040 else 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); 1044 1045 Setattr(n, "proxyfuncname", getter_setter_name); 1046 Setattr(n, "imfuncname", symname); 1047 1048 proxyClassFunctionHandler(n); 1049 Delete(getter_setter_name); 1050 } 1051 1052 Delete(c_return_type); 1053 Delete(im_return_type); 1054 Delete(cleanup); 1055 Delete(outarg); 1056 Delete(body); 1057 Delete(overloaded_name); 1058 DelWrapper(f); 1059 return SWIG_OK; 1060 } 1061 1062 /* ----------------------------------------------------------------------- 1063 * variableWrapper() 1064 * ----------------------------------------------------------------------- */ 1065 1066 virtual int variableWrapper(Node *n) { 1067 Language::variableWrapper(n); 1068 return SWIG_OK; 1069 } 1070 1071 /* ----------------------------------------------------------------------- 1072 * globalvariableHandler() 1073 * ------------------------------------------------------------------------ */ 1074 1075 virtual int globalvariableHandler(Node *n) { 1076 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; 1083 1084 if (proxy_flag) { 1085 Printf(module_class_code, "\n }\n\n"); 1086 } 1087 1088 return ret; 1089 } 1090 1091 /* ---------------------------------------------------------------------- 1092 * enumDeclaration() 1093 * 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 * ---------------------------------------------------------------------- */ 1101 1102 virtual int enumDeclaration(Node *n) { 1103 1104 if (!ImportMode) { 1105 if (getCurrentClass() && (cplus_mode != PUBLIC)) 1106 return SWIG_NOWRAP; 1107 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"); 1113 1114 if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) { 1115 // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum 1116 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); 1120 1121 // Class attributes 1122 const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE); 1123 if (csattributes && *Char(csattributes)) 1124 Printf(enum_code, "%s\n", csattributes); 1125 1126 // Emit the enum 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); 1130 } else { 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); 1134 } 1135 1136 // Emit each enum item 1137 Language::enumDeclaration(n); 1138 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 1145 "}", NIL); 1146 1147 Replaceall(enum_code, "$csclassname", symname); 1148 1149 // Substitute $enumvalues - intended usage is for typesafe enums 1150 if (Getattr(n, "enumvalues")) 1151 Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues")); 1152 else 1153 Replaceall(enum_code, "$enumvalues", ""); 1154 1155 if (proxy_flag && is_wrapping_class()) { 1156 // Enums defined within the C++ class are defined within the proxy class 1157 1158 // Add extra indentation 1159 Replaceall(enum_code, "\n", "\n "); 1160 Replaceall(enum_code, " \n", "\n"); 1161 1162 Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL); 1163 } else { 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()); 1167 if (!f_enum) { 1168 FileErrorDisplay(filen); 1169 SWIG_exit(EXIT_FAILURE); 1170 } 1171 Append(filenames_list, Copy(filen)); 1172 Delete(filen); 1173 filen = NULL; 1174 1175 // Start writing out the enum file 1176 emitBanner(f_enum); 1177 1178 addOpenNamespace(namespce, f_enum); 1179 1180 Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements 1181 "\n", enum_code, "\n", NIL); 1182 1183 addCloseNamespace(namespce, f_enum); 1184 1185 Close(f_enum); 1186 } 1187 } else { 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); 1192 else 1193 Printv(module_class_constants_code, enum_code, NIL); 1194 } 1195 1196 Delete(enum_code); 1197 enum_code = NULL; 1198 } 1199 return SWIG_OK; 1200 } 1201 1202 /* ---------------------------------------------------------------------- 1203 * enumvalueDeclaration() 1204 * ---------------------------------------------------------------------- */ 1205 1206 virtual int enumvalueDeclaration(Node *n) { 1207 if (getCurrentClass() && (cplus_mode != PUBLIC)) 1208 return SWIG_NOWRAP; 1209 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"); 1214 String *tmpValue; 1215 1216 // Strange hack from parent method 1217 if (value) 1218 tmpValue = NewString(value); 1219 else 1220 tmpValue = NewString(name); 1221 // Note that this is used in enumValue() amongst other places 1222 Setattr(n, "value", tmpValue); 1223 1224 { 1225 EnumFeature enum_feature = decodeEnumFeature(parentNode(n)); 1226 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); 1233 1234 // Check for the %csconstvalue feature 1235 String *value = Getattr(n, "feature:cs:constvalue"); 1236 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"); 1239 if (value) { 1240 Printf(enum_code, " = %s", value); 1241 } 1242 } else { 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; 1250 1251 // The %csconst feature determines how the constant value is obtained 1252 int const_feature_flag = GetFlag(n, "feature:cs:const"); 1253 1254 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); 1255 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); 1256 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); 1262 Delete(value); 1263 } else { 1264 Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname); 1265 } 1266 } else { 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); 1273 Delete(value); 1274 } 1275 } 1276 1277 // Add the enum value to the comma separated list being constructed in the enum declaration. 1278 String *enumvalues = Getattr(parentNode(n), "enumvalues"); 1279 if (!enumvalues) 1280 Setattr(parentNode(n), "enumvalues", Copy(symname)); 1281 else 1282 Printv(enumvalues, ", ", symname, NIL); 1283 } 1284 1285 Delete(tmpValue); 1286 Swig_restore(n); 1287 return SWIG_OK; 1288 } 1289 1290 /* ----------------------------------------------------------------------- 1291 * constantWrapper() 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 * ------------------------------------------------------------------------ */ 1300 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"); 1305 String *tm; 1306 String *return_type = NewString(""); 1307 String *constants_code = NewString(""); 1308 1309 if (!addSymbol(symname, n)) 1310 return SWIG_ERROR; 1311 1312 bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0); 1313 1314 // The %csconst feature determines how the constant value is obtained 1315 int const_feature_flag = GetFlag(n, "feature:cs:const"); 1316 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). */ 1319 if (is_enum_item) { 1320 t = Getattr(parentNode(n), "enumtype"); 1321 Setattr(n, "type", t); 1322 } 1323 1324 /* Attach the non-standard typemaps to the parameter list. */ 1325 Swig_typemap_attach_parms("cstype", l, NULL); 1326 1327 /* Get C# return types */ 1328 bool classname_substituted_flag = false; 1329 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 1332 if (cstypeout) 1333 tm = cstypeout; 1334 classname_substituted_flag = substituteClassname(t, tm); 1335 Printf(return_type, "%s", tm); 1336 } else { 1337 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0)); 1338 } 1339 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); 1349 } 1350 1351 const String *outattributes = Getattr(n, "tmap:cstype:outattributes"); 1352 if (outattributes) 1353 Printf(constants_code, " %s\n", outattributes); 1354 const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; 1355 1356 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); 1357 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); 1358 1359 Printf(constants_code, " %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname); 1360 1361 // Check for the %csconstvalue feature 1362 String *value = Getattr(n, "feature:cs:constvalue"); 1363 1364 if (value) { 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. 1368 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)); 1373 } else { 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)); 1376 } 1377 } else 1378 Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname)); 1379 1380 // Each constant and enum value is wrapped with a separate PInvoke function call 1381 SetFlag(n, "feature:immutable"); 1382 enum_constant_flag = true; 1383 variableWrapper(n); 1384 enum_constant_flag = false; 1385 } else { 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")); 1388 } 1389 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); 1395 else 1396 Printv(module_class_constants_code, constants_code, NIL); 1397 } 1398 // Cleanup 1399 Swig_restore(n); 1400 Delete(new_value); 1401 Delete(return_type); 1402 Delete(constants_code); 1403 return SWIG_OK; 1404 } 1405 1406 /* ----------------------------------------------------------------------------- 1407 * insertDirective() 1408 * ----------------------------------------------------------------------------- */ 1409 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); 1416 } 1417 1418 /* ----------------------------------------------------------------------------- 1419 * pragmaDirective() 1420 * 1421 * Valid Pragmas: 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 1427 * 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 1433 * 1434 * ----------------------------------------------------------------------------- */ 1435 1436 virtual int pragmaDirective(Node *n) { 1437 if (!ImportMode) { 1438 String *lang = Getattr(n, "lang"); 1439 String *code = Getattr(n, "name"); 1440 String *value = Getattr(n, "value"); 1441 1442 if (Strcmp(lang, "csharp") == 0) { 1443 1444 String *strvalue = NewString(value); 1445 Replaceall(strvalue, "\\\"", "\""); 1446 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); 1475 } else { 1476 Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number); 1477 } 1478 Delete(strvalue); 1479 } 1480 } 1481 return Language::pragmaDirective(n); 1482 } 1483 1484 /* ----------------------------------------------------------------------------- 1485 * emitProxyClassDefAndCPPCasts() 1486 * ----------------------------------------------------------------------------- */ 1487 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; 1495 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; 1501 Delete(attributes); 1502 1503 // C++ inheritance 1504 if (!purebase_replace) { 1505 List *baselist = Getattr(n, "bases"); 1506 if (baselist) { 1507 Iterator base = First(baselist); 1508 while (base.item && GetFlag(base.item, "feature:ignore")) { 1509 base = Next(base); 1510 } 1511 if (base.item) { 1512 c_baseclassname = Getattr(base.item, "name"); 1513 baseclass = Copy(getProxyName(c_baseclassname)); 1514 if (baseclass) 1515 c_baseclass = SwigType_namestr(Getattr(base.item, "name")); 1516 base = Next(base); 1517 /* Warn about multiple inheritance for additional base class(es) */ 1518 while (base.item) { 1519 if (GetFlag(base.item, "feature:ignore")) { 1520 base = Next(base); 1521 continue; 1522 } 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); 1527 base = Next(base); 1528 } 1529 } 1530 } 1531 } 1532 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; 1537 1538 if (purebase_replace) { 1539 wanted_base = pure_baseclass; 1540 derived = false; 1541 Delete(baseclass); 1542 baseclass = NULL; 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); 1549 } 1550 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 1555 "\n", NIL); 1556 1557 // Class attributes 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); 1561 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 1567 NIL); 1568 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; 1576 if (derived) { 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"); 1580 } else { 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"); 1584 } 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); 1588 } 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); 1592 } 1593 } 1594 // Emit the Finalize and Dispose methods 1595 if (tm) { 1596 // Finalize method 1597 if (*Char(destructor_call)) { 1598 Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL); 1599 } 1600 // Dispose method 1601 Printv(destruct, tm, NIL); 1602 if (*Char(destructor_call)) 1603 Replaceall(destruct, "$imcall", destructor_call); 1604 else 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", 1608 NIL); 1609 } 1610 1611 if (feature_director) { 1612 // Generate director connect method 1613 // put this in classDirectorEnd ??? 1614 Printf(proxy_class_code, " private void SwigDirectorConnect() {\n"); 1615 1616 int i; 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); 1624 } 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); 1630 } 1631 Printf(proxy_class_code, ");\n"); 1632 Printf(proxy_class_code, " }\n"); 1633 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) 1646 { 1647 hasDerivedMethod = true; 1648 ParameterInfo[] parameterArray1 = methodInfo.GetParameters(); 1649 for (int i=0; i<methodTypes.Length; i++) 1650 { 1651 if (parameterArray1[0].ParameterType != methodTypes[0]) 1652 { 1653 hasDerivedMethod = false; 1654 break; 1655 } 1656 } 1657 } 1658 } 1659 */ 1660 Printf(proxy_class_code, " return hasDerivedMethod;\n"); 1661 Printf(proxy_class_code, " }\n"); 1662 } 1663 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); 1672 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; 1687 } 1688 1689 Delete(attributes); 1690 Delete(destruct); 1691 1692 // Emit extra user code 1693 Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code 1694 "\n", NIL); 1695 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); 1699 1700 Replaceall(proxy_class_def, "$module", module_class_name); 1701 Replaceall(proxy_class_code, "$module", module_class_name); 1702 1703 Replaceall(proxy_class_def, "$imclassname", imclass_name); 1704 Replaceall(proxy_class_code, "$imclassname", imclass_name); 1705 1706 Replaceall(proxy_class_def, "$dllimport", dllimport); 1707 Replaceall(proxy_class_code, "$dllimport", dllimport); 1708 1709 // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy) 1710 if (derived) { 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"); 1713 1714 Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); 1715 1716 Printv(upcasts_code, 1717 "SWIGEXPORT $cbaseclass * SWIGSTDCALL CSharp_$imclazznameUpcast", 1718 "($cclass *objectRef) {\n", " return ($cbaseclass *)objectRef;\n" "}\n", "\n", NIL); 1719 1720 Replaceall(upcasts_code, "$cbaseclass", c_baseclass); 1721 Replaceall(upcasts_code, "$imclazzname", proxy_class_name); 1722 Replaceall(upcasts_code, "$cclass", c_classname); 1723 } 1724 Delete(baseclass); 1725 } 1726 1727 /* ---------------------------------------------------------------------- 1728 * classHandler() 1729 * ---------------------------------------------------------------------- */ 1730 1731 virtual int classHandler(Node *n) { 1732 1733 File *f_proxy = NULL; 1734 if (proxy_flag) { 1735 proxy_class_name = NewString(Getattr(n, "sym:name")); 1736 1737 if (!addSymbol(proxy_class_name, n)) 1738 return SWIG_ERROR; 1739 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); 1743 } 1744 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); 1748 } 1749 1750 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), proxy_class_name); 1751 f_proxy = NewFile(filen, "w", SWIG_output_files()); 1752 if (!f_proxy) { 1753 FileErrorDisplay(filen); 1754 SWIG_exit(EXIT_FAILURE); 1755 } 1756 Append(filenames_list, Copy(filen)); 1757 Delete(filen); 1758 filen = NULL; 1759 1760 // Start writing out the proxy class file 1761 emitBanner(f_proxy); 1762 1763 addOpenNamespace(namespce, f_proxy); 1764 1765 Clear(proxy_class_def); 1766 Clear(proxy_class_code); 1767 1768 destructor_call = NewString(""); 1769 proxy_class_constants_code = NewString(""); 1770 } 1771 1772 Language::classHandler(n); 1773 1774 if (proxy_flag) { 1775 1776 emitProxyClassDefAndCPPCasts(n); 1777 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); 1787 1788 Printv(f_proxy, proxy_class_def, proxy_class_code, NIL); 1789 1790 // Write out all the constants 1791 if (Len(proxy_class_constants_code) != 0) 1792 Printv(f_proxy, proxy_class_constants_code, NIL); 1793 1794 Printf(f_proxy, "}\n"); 1795 addCloseNamespace(namespce, f_proxy); 1796 Close(f_proxy); 1797 f_proxy = NULL; 1798 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")); 1805 1806 Printf(imclass_class_code, " public final static native %s downcast%s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, proxy_class_name); 1807 1808 Wrapper *dcast_wrap = NewWrapper(); 1809 1810 Printf(dcast_wrap->def, "SWIGEXPORT jobject SWIGSTDCALL CSharp_downcast%s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {", 1811 proxy_class_name); 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"); 1819 1820 Wrapper_print(dcast_wrap, f_wrappers); 1821 DelWrapper(dcast_wrap); 1822 } 1823 1824 emitDirectorExtraMethods(n); 1825 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; 1832 } 1833 1834 return SWIG_OK; 1835 } 1836 1837 /* ---------------------------------------------------------------------- 1838 * memberfunctionHandler() 1839 * ---------------------------------------------------------------------- */ 1840 1841 virtual int memberfunctionHandler(Node *n) { 1842 Language::memberfunctionHandler(n); 1843 1844 if (proxy_flag) { 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); 1851 } 1852 return SWIG_OK; 1853 } 1854 1855 /* ---------------------------------------------------------------------- 1856 * staticmemberfunctionHandler() 1857 * ---------------------------------------------------------------------- */ 1858 1859 virtual int staticmemberfunctionHandler(Node *n) { 1860 1861 static_flag = true; 1862 Language::staticmemberfunctionHandler(n); 1863 1864 if (proxy_flag) { 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); 1871 } 1872 static_flag = false; 1873 1874 return SWIG_OK; 1875 } 1876 1877 1878 /* ----------------------------------------------------------------------------- 1879 * proxyClassFunctionHandler() 1880 * 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 * ----------------------------------------------------------------------------- */ 1888 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"); 1894 String *tm; 1895 Parm *p; 1896 Parm *last_parm = 0; 1897 int i; 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(""); 1905 1906 if (!proxy_flag) 1907 return; 1908 1909 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C# 1910 if (Getattr(n, "overload:ignore")) 1911 return; 1912 1913 // Don't generate proxy method for additional explicitcall method used in directors 1914 if (GetFlag(n, "explicitcall")) 1915 return; 1916 1917 if (l) { 1918 if (SwigType_type(Getattr(l, "type")) == T_VOID) { 1919 l = nextSibling(l); 1920 } 1921 } 1922 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); 1927 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 1933 if (cstypeout) 1934 tm = cstypeout; 1935 substituteClassname(covariant ? covariant : t, tm); 1936 Printf(return_type, "%s", tm); 1937 if (covariant) 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)); 1940 } else { 1941 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0)); 1942 } 1943 1944 if (wrapping_member_flag && !enum_constant_flag) { 1945 // Properties 1946 setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0); 1947 if (setter_flag) 1948 Swig_typemap_attach_parms("csvarin", l, NULL); 1949 } 1950 1951 /* Start generating the proxy function */ 1952 const String *outattributes = Getattr(n, "tmap:cstype:outattributes"); 1953 if (outattributes) 1954 Printf(function_code, " %s\n", outattributes); 1955 const String *csattributes = Getattr(n, "feature:cs:attributes"); 1956 if (csattributes) 1957 Printf(function_code, " %s\n", csattributes); 1958 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); 1959 if (methodmods) { 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); 1968 Delete(mmods); 1969 } else { 1970 Printf(function_code, " %s ", methodmods); 1971 } 1972 } else { 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 "); 1983 } 1984 } 1985 if (static_flag) 1986 Printf(function_code, "static "); 1987 Printf(function_code, "%s %s(", return_type, proxy_function_name); 1988 1989 Printv(imcall, imclass_name, ".$imfuncname(", NIL); 1990 if (!static_flag) 1991 Printf(imcall, "swigCPtr"); 1992 1993 emit_mark_varargs(l); 1994 1995 int gencomma = !static_flag; 1996 1997 /* Output each parameter */ 1998 for (i = 0, p = l; p; i++) { 1999 2000 /* Ignored varargs */ 2001 if (checkAttribute(p, "varargs:ignore", "1")) { 2002 p = nextSibling(p); 2003 continue; 2004 } 2005 2006 /* Ignored parameters */ 2007 if (checkAttribute(p, "tmap:in:numinputs", "0")) { 2008 p = Getattr(p, "tmap:in:next"); 2009 continue; 2010 } 2011 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(""); 2016 if (setter_flag) 2017 last_parm = p; 2018 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); 2024 } else { 2025 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0)); 2026 } 2027 2028 if (gencomma) 2029 Printf(imcall, ", "); 2030 2031 String *arg = makeParameterName(n, p, i, setter_flag); 2032 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"); 2038 if (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); 2044 } 2045 String *post = Getattr(p, "tmap:csin:post"); 2046 if (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); 2052 } 2053 String *terminator = Getattr(p, "tmap:csin:terminator"); 2054 if (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); 2060 } 2061 Printv(imcall, tm, NIL); 2062 } else { 2063 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0)); 2064 } 2065 2066 /* Add parameter to proxy function */ 2067 if (gencomma >= 2) 2068 Printf(function_code, ", "); 2069 gencomma = 2; 2070 Printf(function_code, "%s %s", param_type, arg); 2071 2072 Delete(arg); 2073 Delete(param_type); 2074 } 2075 p = Getattr(p, "tmap:in:next"); 2076 } 2077 2078 Printf(imcall, ")"); 2079 Printf(function_code, ")"); 2080 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 2089 if (is_post_code) { 2090 Insert(tm, 0, "\n try "); 2091 Printv(tm, " finally {\n", post_code, "\n }", NIL); 2092 } else { 2093 Insert(tm, 0, "\n "); 2094 } 2095 if (is_pre_code) { 2096 Insert(tm, 0, pre_code); 2097 Insert(tm, 0, "\n"); 2098 } 2099 if (is_terminator_code) { 2100 Printv(tm, "\n", terminator_code, NIL); 2101 } 2102 Insert(tm, 0, "{"); 2103 Printf(tm, "\n }"); 2104 } 2105 if (GetFlag(n, "feature:new")) 2106 Replaceall(tm, "$owner", "true"); 2107 else 2108 Replaceall(tm, "$owner", "false"); 2109 substituteClassname(t, tm); 2110 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"); 2114 if (explicit_n) { 2115 String *ex_overloaded_name = getOverloadedName(explicit_n); 2116 String *ex_intermediary_function_name = Swig_name_member(proxy_class_name, ex_overloaded_name); 2117 2118 String *ex_imcall = Copy(imcall); 2119 Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name); 2120 Replaceall(imcall, "$imfuncname", intermediary_function_name); 2121 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); 2125 else 2126 Printf(excode, "((this.GetType() == typeof(%s)) ? %s : %s)", proxy_class_name, imcall, ex_imcall); 2127 2128 Clear(imcall); 2129 Printv(imcall, excode, NIL); 2130 Delete(ex_overloaded_name); 2131 Delete(excode); 2132 } else { 2133 Replaceall(imcall, "$imfuncname", intermediary_function_name); 2134 } 2135 Replaceall(tm, "$imcall", imcall); 2136 } else { 2137 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0)); 2138 } 2139 2140 if (wrapping_member_flag && !enum_constant_flag) { 2141 // Properties 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; 2145 if (setter_flag) { 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; 2152 } else { 2153 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0)); 2154 } 2155 } 2156 const String *csattributes = Getattr(n, "feature:cs:attributes"); 2157 if (csattributes) 2158 Printf(proxy_class_code, " %s\n", csattributes); 2159 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); 2160 if (!methodmods) 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); 2163 } 2164 generate_property_declaration_flag = false; 2165 2166 if (setter_flag) { 2167 // Setter method 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); 2175 } else { 2176 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0)); 2177 } 2178 } else { 2179 // Getter method 2180 if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) { 2181 if (GetFlag(n, "feature:new")) 2182 Replaceall(tm, "$owner", "true"); 2183 else 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); 2189 } else { 2190 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0)); 2191 } 2192 } 2193 } else { 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); 2197 } 2198 2199 Delete(pre_code); 2200 Delete(post_code); 2201 Delete(terminator_code); 2202 Delete(function_code); 2203 Delete(return_type); 2204 Delete(imcall); 2205 } 2206 2207 /* ---------------------------------------------------------------------- 2208 * constructorHandler() 2209 * ---------------------------------------------------------------------- */ 2210 2211 virtual int constructorHandler(Node *n) { 2212 2213 ParmList *l = Getattr(n, "parms"); 2214 String *tm; 2215 Parm *p; 2216 int i; 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)); 2225 2226 Language::constructorHandler(n); 2227 2228 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C# 2229 if (Getattr(n, "overload:ignore")) 2230 return SWIG_OK; 2231 2232 if (proxy_flag) { 2233 String *overloaded_name = getOverloadedName(n); 2234 String *mangled_overname = Swig_name_construct(overloaded_name); 2235 String *imcall = NewString(""); 2236 2237 const String *csattributes = Getattr(n, "feature:cs:attributes"); 2238 if (csattributes) { 2239 Printf(function_code, " %s\n", csattributes); 2240 Printf(helper_code, " %s\n", csattributes); 2241 } 2242 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); 2243 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); 2244 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 2247 if (imtypeout) 2248 tm = imtypeout; 2249 Printf(im_return_type, "%s", tm); 2250 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); 2253 2254 Printv(imcall, imclass_name, ".", mangled_overname, "(", NIL); 2255 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); 2260 2261 emit_mark_varargs(l); 2262 2263 int gencomma = 0; 2264 2265 /* Output each parameter */ 2266 for (i = 0, p = l; p; i++) { 2267 2268 /* Ignored varargs */ 2269 if (checkAttribute(p, "varargs:ignore", "1")) { 2270 p = nextSibling(p); 2271 continue; 2272 } 2273 2274 /* Ignored parameters */ 2275 if (checkAttribute(p, "tmap:in:numinputs", "0")) { 2276 p = Getattr(p, "tmap:in:next"); 2277 continue; 2278 } 2279 2280 SwigType *pt = Getattr(p, "type"); 2281 String *param_type = NewString(""); 2282 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); 2288 } else { 2289 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0)); 2290 } 2291 2292 if (gencomma) 2293 Printf(imcall, ", "); 2294 2295 String *arg = makeParameterName(n, p, i, false); 2296 String *cshin = 0; 2297 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"); 2303 if (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); 2309 } 2310 String *post = Getattr(p, "tmap:csin:post"); 2311 if (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); 2317 } 2318 String *terminator = Getattr(p, "tmap:csin:terminator"); 2319 if (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); 2325 } 2326 cshin = Getattr(p, "tmap:csin:cshin"); 2327 if (cshin) 2328 Replaceall(cshin, "$csinput", arg); 2329 Printv(imcall, tm, NIL); 2330 } else { 2331 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0)); 2332 } 2333 2334 /* Add parameter to proxy function */ 2335 if (gencomma) { 2336 Printf(function_code, ", "); 2337 Printf(helper_code, ", "); 2338 Printf(helper_args, ", "); 2339 } 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); 2343 ++gencomma; 2344 2345 Delete(cshin); 2346 Delete(arg); 2347 Delete(param_type); 2348 p = Getattr(p, "tmap:in:next"); 2349 } 2350 2351 Printf(imcall, ")"); 2352 2353 Printf(function_code, ")"); 2354 Printf(helper_code, ")"); 2355 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)); 2360 if (construct_tm) { 2361 if (!feature_director) { 2362 Replaceall(construct_tm, "$directorconnect", ""); 2363 } else { 2364 String *connect_attr = Getattr(attributes, "tmap:csconstruct:directorconnect"); 2365 2366 if (connect_attr) { 2367 Replaceall(construct_tm, "$directorconnect", connect_attr); 2368 } else { 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", ""); 2372 } 2373 } 2374 2375 Printv(function_code, " ", construct_tm, NIL); 2376 } 2377 2378 excodeSubstitute(n, function_code, "csconstruct", attributes); 2379 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"); 2385 if (is_pre_code) { 2386 Printv(helper_code, pre_code, "\n", NIL); 2387 } 2388 if (is_post_code) { 2389 Printf(helper_code, " try {\n"); 2390 Printv(helper_code, " return ", imcall, ";\n", NIL); 2391 Printv(helper_code, " } finally {\n", post_code, "\n }", NIL); 2392 } else { 2393 Printv(helper_code, " return ", imcall, ";", NIL); 2394 } 2395 if (is_terminator_code) { 2396 Printv(helper_code, "\n", terminator_code, NIL); 2397 } 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); 2406 } else { 2407 Replaceall(function_code, "$imcall", imcall); 2408 } 2409 2410 Printv(proxy_class_code, function_code, "\n", NIL); 2411 2412 Delete(helper_args); 2413 Delete(im_return_type); 2414 Delete(pre_code); 2415 Delete(post_code); 2416 Delete(terminator_code); 2417 Delete(construct_tm); 2418 Delete(attributes); 2419 Delete(overloaded_name); 2420 Delete(imcall); 2421 } 2422 2423 return SWIG_OK; 2424 } 2425 2426 /* ---------------------------------------------------------------------- 2427 * destructorHandler() 2428 * ---------------------------------------------------------------------- */ 2429 2430 virtual int destructorHandler(Node *n) { 2431 Language::destructorHandler(n); 2432 String *symname = Getattr(n, "sym:name"); 2433 2434 if (proxy_flag) { 2435 Printv(destructor_call, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL); 2436 } 2437 return SWIG_OK; 2438 } 2439 2440 /* ---------------------------------------------------------------------- 2441 * membervariableHandler() 2442 * ---------------------------------------------------------------------- */ 2443 2444 virtual int membervariableHandler(Node *n) { 2445 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; 2454 2455 Printf(proxy_class_code, "\n }\n\n"); 2456 2457 return SWIG_OK; 2458 } 2459 2460 /* ---------------------------------------------------------------------- 2461 * staticmembervariableHandler() 2462 * ---------------------------------------------------------------------- */ 2463 2464 virtual int staticmembervariableHandler(Node *n) { 2465 2466 bool static_const_member_flag = (Getattr(n, "value") == 0); 2467 2468 generate_property_declaration_flag = true; 2469 variable_name = Getattr(n, "sym:name"); 2470 wrapping_member_flag = true; 2471 static_flag = true; 2472 Language::staticmembervariableHandler(n); 2473 wrapping_member_flag = false; 2474 static_flag = false; 2475 generate_property_declaration_flag = false; 2476 2477 if (static_const_member_flag) 2478 Printf(proxy_class_code, "\n }\n\n"); 2479 2480 return SWIG_OK; 2481 } 2482 2483 /* ---------------------------------------------------------------------- 2484 * memberconstantHandler() 2485 * ---------------------------------------------------------------------- */ 2486 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; 2492 return SWIG_OK; 2493 } 2494 2495 /* ----------------------------------------------------------------------------- 2496 * getOverloadedName() 2497 * ----------------------------------------------------------------------------- */ 2498 2499 String *getOverloadedName(Node *n) { 2500 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 2503 * a unique name. */ 2504 String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name")); 2505 2506 if (Getattr(n, "sym:overloaded")) { 2507 Printv(overloaded_name, Getattr(n, "sym:overname"), NIL); 2508 } 2509 2510 return overloaded_name; 2511 } 2512 2513 /* ----------------------------------------------------------------------------- 2514 * moduleClassFunctionHandler() 2515 * ----------------------------------------------------------------------------- */ 2516 2517 void moduleClassFunctionHandler(Node *n) { 2518 SwigType *t = Getattr(n, "type"); 2519 ParmList *l = Getattr(n, "parms"); 2520 String *tm; 2521 Parm *p; 2522 Parm *last_parm = 0; 2523 int i; 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(""); 2535 2536 if (l) { 2537 if (SwigType_type(Getattr(l, "type")) == T_VOID) { 2538 l = nextSibling(l); 2539 } 2540 } 2541 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); 2545 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 2549 if (cstypeout) 2550 tm = cstypeout; 2551 substituteClassname(t, tm); 2552 Printf(return_type, "%s", tm); 2553 } else { 2554 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0)); 2555 } 2556 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); 2562 if (setter_flag) 2563 Printf(func_name, "set"); 2564 else 2565 Printf(func_name, "get"); 2566 Putc(toupper((int) *Char(variable_name)), func_name); 2567 Printf(func_name, "%s", Char(variable_name) + 1); 2568 if (setter_flag) 2569 Swig_typemap_attach_parms("csvarin", l, NULL); 2570 } else { 2571 func_name = Copy(Getattr(n, "sym:name")); 2572 } 2573 2574 /* Start generating the function */ 2575 const String *outattributes = Getattr(n, "tmap:cstype:outattributes"); 2576 if (outattributes) 2577 Printf(function_code, " %s\n", outattributes); 2578 const String *csattributes = Getattr(n, "feature:cs:attributes"); 2579 if (csattributes) 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); 2585 2586 /* Get number of required and total arguments */ 2587 num_arguments = emit_num_arguments(l); 2588 num_required = emit_num_required(l); 2589 2590 bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag); 2591 int gencomma = 0; 2592 2593 /* Output each parameter */ 2594 for (i = 0, p = l; i < num_arguments; i++) { 2595 2596 /* Ignored parameters */ 2597 while (checkAttribute(p, "tmap:in:numinputs", "0")) { 2598 p = Getattr(p, "tmap:in:next"); 2599 } 2600 2601 SwigType *pt = Getattr(p, "type"); 2602 String *param_type = NewString(""); 2603 last_parm = p; 2604 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); 2610 } else { 2611 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0)); 2612 } 2613 2614 if (gencomma) 2615 Printf(imcall, ", "); 2616 2617 String *arg = makeParameterName(n, p, i, global_or_member_variable); 2618 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"); 2624 if (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); 2630 } 2631 String *post = Getattr(p, "tmap:csin:post"); 2632 if (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); 2638 } 2639 String *terminator = Getattr(p, "tmap:csin:terminator"); 2640 if (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); 2646 } 2647 Printv(imcall, tm, NIL); 2648 } else { 2649 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0)); 2650 } 2651 2652 /* Add parameter to module class function */ 2653 if (gencomma >= 2) 2654 Printf(function_code, ", "); 2655 gencomma = 2; 2656 Printf(function_code, "%s %s", param_type, arg); 2657 2658 p = Getattr(p, "tmap:in:next"); 2659 Delete(arg); 2660 Delete(param_type); 2661 } 2662 2663 Printf(imcall, ")"); 2664 Printf(function_code, ")"); 2665 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 2674 if (is_post_code) { 2675 Insert(tm, 0, "\n try "); 2676 Printv(tm, " finally {\n", post_code, "\n }", NIL); 2677 } else { 2678 Insert(tm, 0, "\n "); 2679 } 2680 if (is_pre_code) { 2681 Insert(tm, 0, pre_code); 2682 Insert(tm, 0, "\n"); 2683 } 2684 if (is_terminator_code) { 2685 Printv(tm, "\n", terminator_code, NIL); 2686 } 2687 Insert(tm, 0, "{"); 2688 Printf(tm, "\n }"); 2689 } 2690 if (GetFlag(n, "feature:new")) 2691 Replaceall(tm, "$owner", "true"); 2692 else 2693 Replaceall(tm, "$owner", "false"); 2694 substituteClassname(t, tm); 2695 Replaceall(tm, "$imcall", imcall); 2696 } else { 2697 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0)); 2698 } 2699 2700 if (proxy_flag && global_variable_flag) { 2701 // Properties 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; 2705 if (setter_flag) { 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; 2712 } else { 2713 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0)); 2714 } 2715 } 2716 const String *csattributes = Getattr(n, "feature:cs:attributes"); 2717 if (csattributes) 2718 Printf(module_class_code, " %s\n", csattributes); 2719 const String *methodmods = Getattr(n, "feature:cs:methodmodifiers"); 2720 if (!methodmods) 2721 methodmods = (is_public(n) ? public_string : protected_string); 2722 Printf(module_class_code, " %s static %s %s {", methodmods, variable_type, variable_name); 2723 } 2724 generate_property_declaration_flag = false; 2725 2726 if (setter_flag) { 2727 // Setter method 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); 2736 } else { 2737 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0)); 2738 } 2739 } else { 2740 // Getter method 2741 if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) { 2742 if (GetFlag(n, "feature:new")) 2743 Replaceall(tm, "$owner", "true"); 2744 else 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); 2750 } else { 2751 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0)); 2752 } 2753 } 2754 } else { 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); 2758 } 2759 2760 Delete(pre_code); 2761 Delete(post_code); 2762 Delete(terminator_code); 2763 Delete(function_code); 2764 Delete(return_type); 2765 Delete(imcall); 2766 Delete(func_name); 2767 } 2768 2769 /*---------------------------------------------------------------------- 2770 * replaceSpecialVariables() 2771 *--------------------------------------------------------------------*/ 2772 2773 virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) { 2774 (void)method; 2775 SwigType *type = Getattr(parm, "type"); 2776 substituteClassname(type, tm); 2777 } 2778 2779 /*---------------------------------------------------------------------- 2780 * decodeEnumFeature() 2781 * Decode the possible enum features, which are one of: 2782 * %csenum(simple) 2783 * %csenum(typeunsafe) - default 2784 * %csenum(typesafe) 2785 * %csenum(proper) 2786 *--------------------------------------------------------------------*/ 2787 2788 EnumFeature decodeEnumFeature(Node *n) { 2789 EnumFeature enum_feature = TypeunsafeEnum; 2790 String *feature = Getattr(n, "feature:cs:enum"); 2791 if (feature) { 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; 2798 } 2799 return enum_feature; 2800 } 2801 2802 /* ----------------------------------------------------------------------- 2803 * enumValue() 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 * ------------------------------------------------------------------------ */ 2812 2813 String *enumValue(Node *n) { 2814 String *symname = Getattr(n, "sym:name"); 2815 2816 // Check for the %csconstvalue feature 2817 String *value = Getattr(n, "feature:cs:constvalue"); 2818 2819 if (!value) { 2820 // The %csconst feature determines how the constant value is obtained 2821 int const_feature_flag = GetFlag(n, "feature:cs:const"); 2822 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")); 2826 } else { 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 */ 2831 constantWrapper(n); 2832 value = NewStringf("%s.%s()", imclass_name, Swig_name_get(symname)); 2833 } else { 2834 memberconstantHandler(n); 2835 value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname))); 2836 } 2837 } 2838 } 2839 return value; 2840 } 2841 2842 /* ----------------------------------------------------------------------------- 2843 * getEnumName() 2844 * ----------------------------------------------------------------------------- */ 2845 2846 String *getEnumName(SwigType *t) { 2847 Node *enum_name = NULL; 2848 Node *n = enumLookup(t); 2849 if (n) { 2850 String *symname = Getattr(n, "sym:name"); 2851 if (symname) { 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); 2857 } 2858 if (proxyname) 2859 enum_name = NewStringf("%s.%s", proxyname, symname); 2860 else 2861 enum_name = NewStringf("%s", symname); 2862 Delete(scopename_prefix); 2863 } 2864 } 2865 2866 return enum_name; 2867 } 2868 2869 /* ----------------------------------------------------------------------------- 2870 * substituteClassname() 2871 * 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. 2876 * Inputs: 2877 * pt - parameter type 2878 * tm - typemap contents that might contain the special variable to be replaced 2879 * Outputs: 2880 * tm - typemap contents complete with the special variable substitution 2881 * Return: 2882 * substitution_performed - flag indicating if a substitution was performed 2883 * ----------------------------------------------------------------------------- */ 2884 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); 2889 2890 if (Strstr(tm, "$csclassname")) { 2891 SwigType *classnametype = Copy(strippedtype); 2892 substituteClassnameSpecialVariable(classnametype, tm, "$csclassname"); 2893 substitution_performed = true; 2894 Delete(classnametype); 2895 } 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); 2902 } 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); 2909 } 2910 2911 Delete(strippedtype); 2912 Delete(type); 2913 2914 return substitution_performed; 2915 } 2916 2917 /* ----------------------------------------------------------------------------- 2918 * substituteClassnameSpecialVariable() 2919 * ----------------------------------------------------------------------------- */ 2920 2921 void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) { 2922 if (SwigType_isenum(classnametype)) { 2923 String *enumname = getEnumName(classnametype); 2924 if (enumname) 2925 Replaceall(tm, classnamespecialvariable, enumname); 2926 else 2927 Replaceall(tm, classnamespecialvariable, NewStringf("int")); 2928 } else { 2929 String *classname = getProxyName(classnametype); 2930 if (classname) { 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); 2935 2936 // Add to hash table so that the type wrapper classes can be created later 2937 Setattr(swig_types_hash, descriptor, classnametype); 2938 Delete(descriptor); 2939 } 2940 } 2941 } 2942 2943 /* ----------------------------------------------------------------------------- 2944 * makeParameterName() 2945 * 2946 * Inputs: 2947 * n - Node 2948 * p - parameter node 2949 * arg_num - parameter argument number 2950 * setter - set this flag when wrapping variables 2951 * Return: 2952 * arg - a unique parameter name 2953 * ----------------------------------------------------------------------------- */ 2954 2955 String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) { 2956 2957 String *arg = 0; 2958 String *pn = Getattr(p, "name"); 2959 2960 // Use C parameter name unless it is a duplicate or an empty parameter name 2961 int count = 0; 2962 ParmList *plist = Getattr(n, "parms"); 2963 while (plist) { 2964 if ((Cmp(pn, Getattr(plist, "name")) == 0)) 2965 count++; 2966 plist = nextSibling(plist); 2967 } 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); 2970 2971 if (setter && Cmp(arg, "self") != 0) { 2972 // Note that in C# properties, the input variable name is always called 'value' 2973 Delete(arg); 2974 arg = NewString("value"); 2975 } 2976 2977 return arg; 2978 } 2979 2980 /* ----------------------------------------------------------------------------- 2981 * emitTypeWrapperClass() 2982 * ----------------------------------------------------------------------------- */ 2983 2984 void emitTypeWrapperClass(String *classname, SwigType *type) { 2985 Node *n = NewHash(); 2986 Setfile(n, input_file); 2987 Setline(n, line_number); 2988 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()); 2992 if (!f_swigtype) { 2993 FileErrorDisplay(filen); 2994 SWIG_exit(EXIT_FAILURE); 2995 } 2996 Append(filenames_list, Copy(filen)); 2997 Delete(filen); 2998 filen = NULL; 2999 3000 // Start writing out the type wrapper class file 3001 emitBanner(f_swigtype); 3002 3003 addOpenNamespace(namespce, f_swigtype); 3004 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); 3008 3009 // Emit the class 3010 Printv(swigtype, typemapLookup(n, "csimports", type, WARN_NONE), // Import statements 3011 "\n", NIL); 3012 3013 // Class attributes 3014 const String *csattributes = typemapLookup(n, "csattributes", type, WARN_NONE); 3015 if (csattributes && *Char(csattributes)) 3016 Printf(swigtype, "%s\n", csattributes); 3017 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 3023 "}\n", NIL); 3024 3025 Replaceall(swigtype, "$csclassname", classname); 3026 Replaceall(swigtype, "$module", module_class_name); 3027 Replaceall(swigtype, "$imclassname", imclass_name); 3028 Replaceall(swigtype, "$dllimport", dllimport); 3029 3030 Printv(f_swigtype, swigtype, NIL); 3031 3032 addCloseNamespace(namespce, f_swigtype); 3033 3034 Close(f_swigtype); 3035 Delete(swigtype); 3036 Delete(n); 3037 } 3038 3039 /* ----------------------------------------------------------------------------- 3040 * typemapLookup() 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 * ----------------------------------------------------------------------------- */ 3049 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); 3056 if (!tm) { 3057 tm = empty_string; 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)); 3060 } 3061 if (!typemap_attributes) 3062 Delete(node); 3063 return tm; 3064 } 3065 3066 /* ----------------------------------------------------------------------------- 3067 * canThrow() 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 * ----------------------------------------------------------------------------- */ 3071 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); 3075 if (canthrow) 3076 Setattr(n, "csharp:canthrow", "1"); 3077 Delete(canthrow_attribute); 3078 } 3079 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 * ----------------------------------------------------------------------------- */ 3087 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); 3096 } 3097 } else { 3098 Replaceall(code, "$excode", empty_string); 3099 } 3100 Delete(excode_attribute); 3101 } 3102 3103 /* ----------------------------------------------------------------------------- 3104 * addOpenNamespace() 3105 * ----------------------------------------------------------------------------- */ 3106 3107 void addOpenNamespace(String *namspace, File *file) { 3108 if (namspace) 3109 if (Len(namspace) > 0) 3110 Printf(file, "namespace %s {\n", namspace); 3111 } 3112 3113 /* ----------------------------------------------------------------------------- 3114 * addCloseNamespace() 3115 * ----------------------------------------------------------------------------- */ 3116 3117 void addCloseNamespace(String *namspace, File *file) { 3118 if (namspace) 3119 if (Len(namspace) > 0) 3120 Printf(file, "\n}\n"); 3121 } 3122 3123 /*---------------------------------------------------------------------- 3124 * Start of director methods 3125 *--------------------------------------------------------------------*/ 3126 3127#if 0 3128 /*---------------------------------------------------------------------- 3129 * emitDirectorUpcalls() 3130 *--------------------------------------------------------------------*/ 3131 3132 void emitDirectorUpcalls() { 3133 if (n_dmethods) { 3134 Wrapper *w = NewWrapper(); 3135 String *dmethod_data = NewString(""); 3136 int n_methods = 0; 3137 Iterator udata_iter; 3138 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")); 3143 ++n_methods; 3144 3145 udata_iter = Next(udata_iter); 3146 3147 if (udata_iter.item) 3148 Putc(',', dmethod_data); 3149 Putc('\n', dmethod_data); 3150 } 3151 3152 3153 Wrapper_print(w, f_wrappers); 3154 Delete(dmethod_data); 3155 Delete(swig_module_init); 3156 DelWrapper(w); 3157 } 3158 } 3159#endif 3160 3161 /*---------------------------------------------------------------------- 3162 * emitDirectorExtraMethods() 3163 * 3164 * This is where the director connect method is 3165 * generated. 3166 *--------------------------------------------------------------------*/ 3167 void emitDirectorExtraMethods(Node *n) { 3168 if (!Swig_directorclass(n)) 3169 return; 3170 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"); 3175 Wrapper *code_wrap; 3176 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); 3179 3180 code_wrap = NewWrapper(); 3181 Printf(code_wrap->def, "SWIGEXPORT void SWIGSTDCALL CSharp_%s(void *objarg", swig_director_connect); 3182 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("); 3188 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"); 3192 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); 3199 } 3200 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"); 3206 3207 Wrapper_print(code_wrap, f_wrappers); 3208 DelWrapper(code_wrap); 3209 3210 Delete(swig_director_connect); 3211 } 3212 3213 /* --------------------------------------------------------------- 3214 * classDirectorMethod() 3215 * 3216 * Emit a virtual director method to pass a method call on to the 3217 * underlying Java object. 3218 * 3219 * --------------------------------------------------------------- */ 3220 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(""); 3234 String *tm; 3235 Parm *p; 3236 int i; 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(""); 3255 int gencomma = 0; 3256 bool ignored_method = GetFlag(n, "feature:ignore") ? true : false; 3257 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?) 3262 3263 imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(classname, overloaded_name)); 3264 3265 if (returntype) { 3266 3267 qualified_return = SwigType_rcaststr(returntype, "c_result"); 3268 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); 3275 } else { 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); 3280 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); 3285 } else { 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); 3290 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); 3296 3297 Delete(non_ref_type); 3298 } 3299 3300 Delete(base_typename); 3301 Delete(resolved_typename); 3302 } 3303 } else { 3304 SwigType *vt; 3305 3306 vt = cplus_value_type(returntype); 3307 if (!vt) { 3308 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL); 3309 } else { 3310 Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL); 3311 Delete(vt); 3312 } 3313 } 3314 } 3315 3316 /* Create the intermediate class wrapper */ 3317 Parm *tp = NewParmFromNode(returntype, empty_str, n); 3318 3319 tm = Swig_typemap_lookup("imtype", tp, "", 0); 3320 if (tm) { 3321 String *imtypeout = Getattr(tp, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap 3322 if (imtypeout) 3323 tm = imtypeout; 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); 3328 } 3329 3330 Printf(callback_def, " private %s SwigDirector%s(", tm, overloaded_name); 3331 if (!ignored_method) 3332 Printf(director_delegate_definitions, " public delegate %s", tm); 3333 } else { 3334 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0)); 3335 } 3336 3337 Parm *retpm = NewParmFromNode(returntype, empty_str, n); 3338 3339 if ((c_ret_type = Swig_typemap_lookup("ctype", retpm, "", 0))) { 3340 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); 3345 } 3346 } else { 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; 3350 } 3351 3352 Delete(retpm); 3353 } 3354 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(""); 3359 3360 if (!arg && Cmp(Getattr(p, "type"), "void")) { 3361 lname = NewStringf("arg%d", i); 3362 Setattr(p, "name", lname); 3363 } else 3364 lname = arg; 3365 3366 Setattr(p, "lname", lname); 3367 } 3368 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); 3376 3377 /* Preamble code */ 3378 if (!ignored_method) 3379 Printf(w->code, "if (!swig_callback%s) {\n", overloaded_name); 3380 3381 if (!pure_virtual) { 3382 String *super_call = Swig_method_call(super, l); 3383 if (is_void) { 3384 Printf(w->code, "%s;\n", super_call); 3385 if (!ignored_method) 3386 Printf(w->code, "return;\n"); 3387 } else { 3388 Printf(w->code, "return %s;\n", super_call); 3389 } 3390 Delete(super_call); 3391 } else { 3392 Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); 3393 } 3394 3395 if (!ignored_method) 3396 Printf(w->code, "} else {\n"); 3397 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"); 3403 } 3404 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(""); 3410 3411 Printf(arg, "j%s", ln); 3412 3413 /* And add to the upcall args */ 3414 if (gencomma > 0) 3415 Printf(jupcall_args, ", "); 3416 Printf(jupcall_args, "%s", arg); 3417 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 3421 if (ctypeout) 3422 c_param_type = ctypeout; 3423 3424 Parm *tp = NewParmFromNode(c_param_type, empty_str, n); 3425 String *desc_tm = NULL; 3426 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); 3431 3432 /* Add input marshalling code */ 3433 if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0)) 3434 && (tm = Getattr(p, "tmap:directorin"))) { 3435 3436 Replaceall(tm, "$input", arg); 3437 Replaceall(tm, "$owner", "0"); 3438 3439 if (Len(tm)) 3440 if (!ignored_method) 3441 Printf(w->code, "%s\n", tm); 3442 3443 Delete(tm); 3444 3445 /* Add C type to callback typedef */ 3446 if (gencomma > 0) 3447 Printf(callback_typedef_parms, ", "); 3448 Printf(callback_typedef_parms, "%s", c_param_type); 3449 3450 /* Add parameter to the intermediate class code if generating the 3451 * intermediate's upcall code */ 3452 if ((tm = Getattr(p, "tmap:imtype"))) { 3453 3454 String *imtypeout = Getattr(p, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap 3455 if (imtypeout) 3456 tm = imtypeout; 3457 const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes"); 3458 3459 String *din = Copy(Getattr(p, "tmap:csdirectorin")); 3460 3461 if (din) { 3462 Replaceall(din, "$module", module_class_name); 3463 Replaceall(din, "$imclassname", imclass_name); 3464 substituteClassname(pt, din); 3465 Replaceall(din, "$iminput", ln); 3466 3467 if (gencomma > 0) { 3468 Printf(delegate_parms, ", "); 3469 Printf(proxy_method_types, ", "); 3470 Printf(imcall_args, ", "); 3471 } 3472 Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln); 3473 3474 if (Cmp(din, ln)) { 3475 Printv(imcall_args, din, NIL); 3476 } else 3477 Printv(imcall_args, ln, NIL); 3478 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); 3483 } else { 3484 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0)); 3485 } 3486 } else { 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; 3490 } 3491 } else { 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; 3495 } 3496 3497 p = Getattr(p, "tmap:directorin:next"); 3498 3499 Delete(desc_tm); 3500 } else { 3501 if (!desc_tm) { 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)); 3505 p = nextSibling(p); 3506 } else if (!tm) { 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)); 3510 p = nextSibling(p); 3511 } 3512 3513 output_director = false; 3514 } 3515 3516 Delete(tp); 3517 } else { 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; 3521 p = nextSibling(p); 3522 } 3523 3524 gencomma++; 3525 Delete(arg); 3526 Delete(c_decl); 3527 Delete(c_param_type); 3528 } 3529 3530 /* header declaration, start wrapper definition */ 3531 String *target; 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); 3536 Delete(target); 3537 target = Swig_method_decl(rtype, decl, name, l, 0, 1); 3538 Printf(declaration, " virtual %s", target); 3539 Delete(target); 3540 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")) { 3544 int gencomma = 0; 3545 3546 Append(w->def, " throw("); 3547 Append(declaration, " throw("); 3548 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"))) { 3553 if (gencomma++) { 3554 Append(w->def, ", "); 3555 Append(declaration, ", "); 3556 } 3557 Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0)); 3558 Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0)); 3559 } 3560 } 3561 3562 Append(w->def, ")"); 3563 Append(declaration, ")"); 3564 } 3565 3566 Append(w->def, " {"); 3567 Append(declaration, ";\n"); 3568 3569 /* Finish off the inherited upcall's definition */ 3570 3571 Printf(callback_def, "%s)", delegate_parms); 3572 Printf(callback_def, " {\n"); 3573 3574 /* Emit the intermediate class's upcall to the actual class */ 3575 3576 String *upcall = NewStringf("%s(%s)", symname, imcall_args); 3577 3578 if (!is_void) { 3579 Parm *tp = NewParmFromNode(returntype, empty_str, n); 3580 3581 if ((tm = Swig_typemap_lookup("csdirectorout", tp, "", 0))) { 3582 substituteClassname(returntype, tm); 3583 Replaceall(tm, "$cscall", upcall); 3584 3585 Printf(callback_code, " return %s;\n", tm); 3586 } 3587 3588 Delete(tm); 3589 Delete(tp); 3590 } else 3591 Printf(callback_code, " %s;\n", upcall); 3592 3593 Printf(callback_code, " }\n"); 3594 Delete(upcall); 3595 3596 if (!ignored_method) { 3597 if (!is_void) 3598 Printf(w->code, "jresult = (%s) ", c_ret_type); 3599 3600 Printf(w->code, "swig_callback%s(%s);\n", overloaded_name, jupcall_args); 3601 3602 if (!is_void) { 3603 String *jresult_str = NewString("jresult"); 3604 String *result_str = NewString("c_result"); 3605 Parm *tp = NewParmFromNode(returntype, result_str, n); 3606 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); 3612 } else { 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; 3617 } 3618 3619 Delete(tp); 3620 Delete(jresult_str); 3621 Delete(result_str); 3622 } 3623 3624 /* Terminate wrapper code */ 3625 Printf(w->code, "}\n"); 3626 if (!is_void) 3627 Printf(w->code, "return %s;", qualified_return); 3628 } 3629 3630 Printf(w->code, "}"); 3631 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 "); 3639 if (!is_void) 3640 Printf(inline_extra_method, "return "); 3641 String *methodcall = Swig_method_call(super, l); 3642 Printv(inline_extra_method, methodcall, ";\n }\n", NIL); 3643 Delete(methodcall); 3644 Delete(extra_method_name); 3645 } 3646 3647 /* emit code */ 3648 if (status == SWIG_OK && output_director) { 3649 if (!is_void) { 3650 Replaceall(w->code, "$null", qualified_return); 3651 } else { 3652 Replaceall(w->code, "$null", ""); 3653 } 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); 3660 } 3661 } 3662 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"); 3667 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); 3671 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); 3676 } 3677 3678 Delete(qualified_return); 3679 Delete(c_ret_type); 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); 3686 DelWrapper(w); 3687 3688 return status; 3689 } 3690 3691 /* ------------------------------------------------------------ 3692 * classDirectorConstructor() 3693 * ------------------------------------------------------------ */ 3694 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(""); 3701 Parm *p; 3702 ParmList *superparms = Getattr(n, "parms"); 3703 ParmList *parms; 3704 int argidx = 0; 3705 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"); 3709 3710 if (!pname) { 3711 pname = NewStringf("arg%d", argidx++); 3712 Setattr(p, "name", pname); 3713 } 3714 } 3715 3716 // TODO: Is this copy needed? 3717 parms = CopyParmList(superparms); 3718 3719 if (!Getattr(n, "defaultargs")) { 3720 /* constructor */ 3721 { 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")); 3726 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"); 3730 3731 Delete(classtype); 3732 Delete(target); 3733 Delete(call); 3734 } 3735 3736 /* constructor header */ 3737 { 3738 String *target = Swig_method_decl(0, decl, classname, parms, 0, 1); 3739 Printf(f_directors_h, " %s;\n", target); 3740 Delete(target); 3741 } 3742 } 3743 3744 Delete(sub); 3745 Delete(supername); 3746 Delete(parms); 3747 return Language::classDirectorConstructor(n); 3748 } 3749 3750 /* ------------------------------------------------------------ 3751 * classDirectorDefaultConstructor() 3752 * ------------------------------------------------------------ */ 3753 3754 int classDirectorDefaultConstructor(Node *n) { 3755 String *classname = Swig_class_name(n); 3756 String *classtype = SwigType_namestr(Getattr(n, "name")); 3757 Wrapper *w = NewWrapper(); 3758 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); 3762 3763 Printf(f_directors_h, " SwigDirector_%s();\n", classname); 3764 DelWrapper(w); 3765 Delete(classtype); 3766 Delete(classname); 3767 return Language::classDirectorDefaultConstructor(n); 3768 } 3769 3770 3771 /* ------------------------------------------------------------ 3772 * classDirectorInit() 3773 * ------------------------------------------------------------ */ 3774 3775 int classDirectorInit(Node *n) { 3776 Delete(none_comparison); 3777 none_comparison = NewString(""); // not used 3778 3779 Delete(director_ctor_code); 3780 director_ctor_code = NewString("$director_new"); 3781 3782 Java_director_declaration(n); 3783 3784 Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl")); 3785 Printf(f_directors_h, "\npublic:\n"); 3786 3787 /* Keep track of the director methods for this class */ 3788 first_class_dmethod = curr_class_dmethod = n_dmethods; 3789 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(""); 3797 3798 return Language::classDirectorInit(n); 3799 } 3800 3801 /* ---------------------------------------------------------------------- 3802 * classDirectorDestructor() 3803 * ---------------------------------------------------------------------- */ 3804 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(); 3810 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); 3814 } else { 3815 Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname); 3816 Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname); 3817 } 3818 3819 /* Ensure that correct directordisconnect typemap's method name is called 3820 * here: */ 3821 3822 const String *disconn_tm = NULL; 3823 Node *disconn_attr = NewHash(); 3824 String *disconn_methodname = NULL; 3825 3826 disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr); 3827 disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname"); 3828 3829 Printv(w->code, "}\n", NIL); 3830 3831 Wrapper_print(w, f_directors); 3832 3833 DelWrapper(w); 3834 Delete(disconn_attr); 3835 Delete(classname); 3836 return SWIG_OK; 3837 } 3838 3839 /* ------------------------------------------------------------ 3840 * classDirectorEnd() 3841 * ------------------------------------------------------------ */ 3842 3843 int classDirectorEnd(Node *n) { 3844 int i; 3845 String *director_classname = directorClassName(n); 3846 3847 Wrapper *w = NewWrapper(); 3848 3849 if (Len(director_callback_typedefs) > 0) { 3850 Printf(f_directors_h, "\n%s", director_callback_typedefs); 3851 } 3852 3853 Printf(f_directors_h, " void swig_connect_director("); 3854 3855 Printf(w->def, "void %s::swig_connect_director(", director_classname); 3856 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"); 3861 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, ", "); 3868 } 3869 } 3870 3871 Printf(f_directors_h, ");\n"); 3872 Printf(w->def, ") {"); 3873 3874 3875 if (Len(director_callback_typedefs) > 0) { 3876 Printf(f_directors_h, "\nprivate:\n%s", director_callbacks); 3877 } 3878 Printf(f_directors_h, " void swig_init_callbacks();\n"); 3879 Printf(f_directors_h, "};\n\n"); 3880 Printf(w->code, "}\n\n"); 3881 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); 3887 } 3888 Printf(w->code, "}"); 3889 3890 Wrapper_print(w, f_directors); 3891 3892 DelWrapper(w); 3893 3894 return Language::classDirectorEnd(n); 3895 } 3896 3897 /* -------------------------------------------------------------------- 3898 * classDirectorDisown() 3899 * ------------------------------------------------------------------*/ 3900 virtual int classDirectorDisown(Node *n) { 3901 (void) n; 3902 return SWIG_OK; 3903 } 3904 3905 /*---------------------------------------------------------------------- 3906 * extraDirectorProtectedCPPMethodsRequired() 3907 *--------------------------------------------------------------------*/ 3908 3909 bool extraDirectorProtectedCPPMethodsRequired() const { 3910 return false; 3911 } 3912 3913 /*---------------------------------------------------------------------- 3914 * Java_director_declaration() 3915 * 3916 * Generate the director class's declaration 3917 * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {" 3918 *--------------------------------------------------------------------*/ 3919 3920 void Java_director_declaration(Node *n) { 3921 3922 String *base = Getattr(n, "classtype"); 3923 String *class_ctor = NewString("Swig::Director()"); 3924 3925 String *classname = Swig_class_name(n); 3926 String *directorname = NewStringf("SwigDirector_%s", classname); 3927 String *declaration = Swig_class_declaration(n, directorname); 3928 3929 Printf(declaration, " : public %s, public Swig::Director", base); 3930 3931 // Stash stuff for later. 3932 Setattr(n, "director:decl", declaration); 3933 Setattr(n, "director:ctor", class_ctor); 3934 } 3935 3936}; /* class CSHARP */ 3937 3938/* ----------------------------------------------------------------------------- 3939 * swig_csharp() - Instantiate module 3940 * ----------------------------------------------------------------------------- */ 3941 3942static Language *new_swig_csharp() { 3943 return new CSHARP(); 3944} 3945extern "C" Language *swig_csharp(void) { 3946 return new_swig_csharp(); 3947} 3948 3949/* ----------------------------------------------------------------------------- 3950 * Static member variables 3951 * ----------------------------------------------------------------------------- */ 3952 3953const char *CSHARP::usage = (char *) "\ 3954C# 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\ 3958 of proxy classes\n\ 3959 -oldvarnames - old intermediary method names for variable wrappers\n\ 3960\n"; 3961