PageRenderTime 66ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/trunk/Source/Modules/csharp.cxx

#
C++ | 1760 lines | 1260 code | 248 blank | 252 comment | 315 complexity | b79e1b52544bd3dacf035110a22b9107 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at http://www.swig.org/legal.html.
  8. *
  9. * csharp.cxx
  10. *
  11. * C# language module for SWIG.
  12. * ----------------------------------------------------------------------------- */
  13. char cvsroot_csharp_cxx[] = "$Id: csharp.cxx 12892 2012-01-07 22:09:28Z wsfulton $";
  14. #include "swigmod.h"
  15. #include <limits.h> // for INT_MAX
  16. #include "cparse.h"
  17. #include <ctype.h>
  18. /* Hash type used for upcalls from C/C++ */
  19. typedef DOH UpcallData;
  20. class CSHARP:public Language {
  21. static const char *usage;
  22. const String *empty_string;
  23. const String *public_string;
  24. const String *protected_string;
  25. Hash *swig_types_hash;
  26. File *f_begin;
  27. File *f_runtime;
  28. File *f_runtime_h;
  29. File *f_header;
  30. File *f_wrappers;
  31. File *f_init;
  32. File *f_directors;
  33. File *f_directors_h;
  34. List *filenames_list;
  35. bool proxy_flag; // Flag for generating proxy classes
  36. bool native_function_flag; // Flag for when wrapping a native function
  37. bool enum_constant_flag; // Flag for when wrapping an enum or constant
  38. bool static_flag; // Flag for when wrapping a static functions or member variables
  39. bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
  40. bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
  41. bool global_variable_flag; // Flag for when wrapping a global variable
  42. bool old_variable_names; // Flag for old style variable names in the intermediary class
  43. bool generate_property_declaration_flag; // Flag for generating properties
  44. String *imclass_name; // intermediary class name
  45. String *module_class_name; // module class name
  46. String *imclass_class_code; // intermediary class code
  47. String *proxy_class_def;
  48. String *proxy_class_code;
  49. String *module_class_code;
  50. String *proxy_class_name; // proxy class name
  51. String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name
  52. String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
  53. String *variable_name; //Name of a variable being wrapped
  54. String *proxy_class_constants_code;
  55. String *module_class_constants_code;
  56. String *enum_code;
  57. String *dllimport; // DllImport attribute name
  58. String *namespce; // Optional namespace name
  59. String *imclass_imports; //intermediary class imports from %pragma
  60. String *module_imports; //module imports from %pragma
  61. String *imclass_baseclass; //inheritance for intermediary class class from %pragma
  62. String *module_baseclass; //inheritance for module class from %pragma
  63. String *imclass_interfaces; //interfaces for intermediary class class from %pragma
  64. String *module_interfaces; //interfaces for module class from %pragma
  65. String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma
  66. String *module_class_modifiers; //class modifiers for module class overriden by %pragma
  67. String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
  68. String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
  69. String *director_callback_typedefs; // Director function pointer typedefs for callbacks
  70. String *director_callbacks; // Director callback function pointer member variables
  71. String *director_delegate_callback; // Director callback method that delegates are set to call
  72. String *director_delegate_definitions; // Director delegates definitions in proxy class
  73. String *director_delegate_instances; // Director delegates member variables in proxy class
  74. String *director_method_types; // Director method types
  75. String *director_connect_parms; // Director delegates parameter list for director connect call
  76. String *destructor_call; //C++ destructor call if any
  77. // Director method stuff:
  78. List *dmethods_seq;
  79. Hash *dmethods_table;
  80. int n_dmethods;
  81. int n_directors;
  82. int first_class_dmethod;
  83. int curr_class_dmethod;
  84. enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
  85. public:
  86. /* -----------------------------------------------------------------------------
  87. * CSHARP()
  88. * ----------------------------------------------------------------------------- */
  89. CSHARP():empty_string(NewString("")),
  90. public_string(NewString("public")),
  91. protected_string(NewString("protected")),
  92. swig_types_hash(NULL),
  93. f_begin(NULL),
  94. f_runtime(NULL),
  95. f_runtime_h(NULL),
  96. f_header(NULL),
  97. f_wrappers(NULL),
  98. f_init(NULL),
  99. f_directors(NULL),
  100. f_directors_h(NULL),
  101. filenames_list(NULL),
  102. proxy_flag(true),
  103. native_function_flag(false),
  104. enum_constant_flag(false),
  105. static_flag(false),
  106. variable_wrapper_flag(false),
  107. wrapping_member_flag(false),
  108. global_variable_flag(false),
  109. old_variable_names(false),
  110. generate_property_declaration_flag(false),
  111. imclass_name(NULL),
  112. module_class_name(NULL),
  113. imclass_class_code(NULL),
  114. proxy_class_def(NULL),
  115. proxy_class_code(NULL),
  116. module_class_code(NULL),
  117. proxy_class_name(NULL),
  118. full_proxy_class_name(NULL),
  119. full_imclass_name(NULL),
  120. variable_name(NULL),
  121. proxy_class_constants_code(NULL),
  122. module_class_constants_code(NULL),
  123. enum_code(NULL),
  124. dllimport(NULL),
  125. namespce(NULL),
  126. imclass_imports(NULL),
  127. module_imports(NULL),
  128. imclass_baseclass(NULL),
  129. module_baseclass(NULL),
  130. imclass_interfaces(NULL),
  131. module_interfaces(NULL),
  132. imclass_class_modifiers(NULL),
  133. module_class_modifiers(NULL),
  134. upcasts_code(NULL),
  135. imclass_cppcasts_code(NULL),
  136. director_callback_typedefs(NULL),
  137. director_callbacks(NULL),
  138. director_delegate_callback(NULL),
  139. director_delegate_definitions(NULL),
  140. director_delegate_instances(NULL),
  141. director_method_types(NULL),
  142. director_connect_parms(NULL),
  143. destructor_call(NULL),
  144. dmethods_seq(NULL),
  145. dmethods_table(NULL),
  146. n_dmethods(0),
  147. n_directors(0) {
  148. /* for now, multiple inheritance in directors is disabled, this
  149. should be easy to implement though */
  150. director_multiple_inheritance = 0;
  151. director_language = 1;
  152. }
  153. /* -----------------------------------------------------------------------------
  154. * getProxyName()
  155. *
  156. * Test to see if a type corresponds to something wrapped with a proxy class.
  157. * Return NULL if not otherwise the proxy class name, fully qualified with
  158. * a namespace if the nspace feature is used.
  159. * ----------------------------------------------------------------------------- */
  160. String *getProxyName(SwigType *t) {
  161. String *proxyname = NULL;
  162. if (proxy_flag) {
  163. Node *n = classLookup(t);
  164. if (n) {
  165. proxyname = Getattr(n, "proxyname");
  166. if (!proxyname) {
  167. String *nspace = Getattr(n, "sym:nspace");
  168. String *symname = Getattr(n, "sym:name");
  169. if (nspace) {
  170. if (namespce)
  171. proxyname = NewStringf("%s.%s.%s", namespce, nspace, symname);
  172. else
  173. proxyname = NewStringf("%s.%s", nspace, symname);
  174. } else {
  175. proxyname = Copy(symname);
  176. }
  177. Setattr(n, "proxyname", proxyname);
  178. Delete(proxyname);
  179. }
  180. }
  181. }
  182. return proxyname;
  183. }
  184. /* -----------------------------------------------------------------------------
  185. * directorClassName()
  186. * ----------------------------------------------------------------------------- */
  187. String *directorClassName(Node *n) {
  188. String *dirclassname;
  189. const char *attrib = "director:classname";
  190. if (!(dirclassname = Getattr(n, attrib))) {
  191. String *classname = Getattr(n, "sym:name");
  192. dirclassname = NewStringf("SwigDirector_%s", classname);
  193. Setattr(n, attrib, dirclassname);
  194. }
  195. return dirclassname;
  196. }
  197. /* ------------------------------------------------------------
  198. * main()
  199. * ------------------------------------------------------------ */
  200. virtual void main(int argc, char *argv[]) {
  201. SWIG_library_directory("csharp");
  202. // Look for certain command line options
  203. for (int i = 1; i < argc; i++) {
  204. if (argv[i]) {
  205. if (strcmp(argv[i], "-dllimport") == 0) {
  206. if (argv[i + 1]) {
  207. dllimport = NewString("");
  208. Printf(dllimport, argv[i + 1]);
  209. Swig_mark_arg(i);
  210. Swig_mark_arg(i + 1);
  211. i++;
  212. } else {
  213. Swig_arg_error();
  214. }
  215. } else if (strcmp(argv[i], "-namespace") == 0) {
  216. if (argv[i + 1]) {
  217. namespce = NewString("");
  218. Printf(namespce, argv[i + 1]);
  219. if (Len(namespce) == 0) {
  220. Delete(namespce);
  221. namespce = 0;
  222. }
  223. Swig_mark_arg(i);
  224. Swig_mark_arg(i + 1);
  225. i++;
  226. } else {
  227. Swig_arg_error();
  228. }
  229. } else if ((strcmp(argv[i], "-noproxy") == 0)) {
  230. Swig_mark_arg(i);
  231. proxy_flag = false;
  232. } else if (strcmp(argv[i], "-oldvarnames") == 0) {
  233. Swig_mark_arg(i);
  234. old_variable_names = true;
  235. } else if (strcmp(argv[i], "-help") == 0) {
  236. Printf(stdout, "%s\n", usage);
  237. }
  238. }
  239. }
  240. // Add a symbol to the parser for conditional compilation
  241. Preprocessor_define("SWIGCSHARP 1", 0);
  242. // Add typemap definitions
  243. SWIG_typemap_lang("csharp");
  244. SWIG_config_file("csharp.swg");
  245. allow_overloading();
  246. }
  247. /* ---------------------------------------------------------------------
  248. * top()
  249. * --------------------------------------------------------------------- */
  250. virtual int top(Node *n) {
  251. // Get any options set in the module directive
  252. Node *optionsnode = Getattr(Getattr(n, "module"), "options");
  253. if (optionsnode) {
  254. if (Getattr(optionsnode, "imclassname"))
  255. imclass_name = Copy(Getattr(optionsnode, "imclassname"));
  256. /* check if directors are enabled for this module. note: this
  257. * is a "master" switch, without which no director code will be
  258. * emitted. %feature("director") statements are also required
  259. * to enable directors for individual classes or methods.
  260. *
  261. * use %module(directors="1") modulename at the start of the
  262. * interface file to enable director generation.
  263. */
  264. if (Getattr(optionsnode, "directors")) {
  265. allow_directors();
  266. }
  267. if (Getattr(optionsnode, "dirprot")) {
  268. allow_dirprot();
  269. }
  270. allow_allprotected(GetFlag(optionsnode, "allprotected"));
  271. }
  272. /* Initialize all of the output files */
  273. String *outfile = Getattr(n, "outfile");
  274. String *outfile_h = Getattr(n, "outfile_h");
  275. if (!outfile) {
  276. Printf(stderr, "Unable to determine outfile\n");
  277. SWIG_exit(EXIT_FAILURE);
  278. }
  279. f_begin = NewFile(outfile, "w", SWIG_output_files());
  280. if (!f_begin) {
  281. FileErrorDisplay(outfile);
  282. SWIG_exit(EXIT_FAILURE);
  283. }
  284. if (directorsEnabled()) {
  285. if (!outfile_h) {
  286. Printf(stderr, "Unable to determine outfile_h\n");
  287. SWIG_exit(EXIT_FAILURE);
  288. }
  289. f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
  290. if (!f_runtime_h) {
  291. FileErrorDisplay(outfile_h);
  292. SWIG_exit(EXIT_FAILURE);
  293. }
  294. }
  295. f_runtime = NewString("");
  296. f_init = NewString("");
  297. f_header = NewString("");
  298. f_wrappers = NewString("");
  299. f_directors_h = NewString("");
  300. f_directors = NewString("");
  301. /* Register file targets with the SWIG file handler */
  302. Swig_register_filebyname("header", f_header);
  303. Swig_register_filebyname("wrapper", f_wrappers);
  304. Swig_register_filebyname("begin", f_begin);
  305. Swig_register_filebyname("runtime", f_runtime);
  306. Swig_register_filebyname("init", f_init);
  307. Swig_register_filebyname("director", f_directors);
  308. Swig_register_filebyname("director_h", f_directors_h);
  309. swig_types_hash = NewHash();
  310. filenames_list = NewList();
  311. // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
  312. if (!imclass_name) {
  313. imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name"));
  314. module_class_name = Copy(Getattr(n, "name"));
  315. } else {
  316. // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
  317. if (Cmp(imclass_name, Getattr(n, "name")) == 0)
  318. module_class_name = NewStringf("%sModule", Getattr(n, "name"));
  319. else
  320. module_class_name = Copy(Getattr(n, "name"));
  321. }
  322. // module class and intermediary classes are always created
  323. addSymbol(imclass_name, n);
  324. addSymbol(module_class_name, n);
  325. imclass_class_code = NewString("");
  326. proxy_class_def = NewString("");
  327. proxy_class_code = NewString("");
  328. module_class_constants_code = NewString("");
  329. imclass_baseclass = NewString("");
  330. imclass_interfaces = NewString("");
  331. imclass_class_modifiers = NewString("");
  332. module_class_code = NewString("");
  333. module_baseclass = NewString("");
  334. module_interfaces = NewString("");
  335. module_imports = NewString("");
  336. module_class_modifiers = NewString("");
  337. imclass_imports = NewString("");
  338. imclass_cppcasts_code = NewString("");
  339. director_connect_parms = NewString("");
  340. upcasts_code = NewString("");
  341. dmethods_seq = NewList();
  342. dmethods_table = NewHash();
  343. n_dmethods = 0;
  344. n_directors = 0;
  345. if (!dllimport)
  346. dllimport = Copy(module_class_name);
  347. Swig_banner(f_begin);
  348. Printf(f_runtime, "\n");
  349. Printf(f_runtime, "#define SWIGCSHARP\n");
  350. if (directorsEnabled()) {
  351. Printf(f_runtime, "#define SWIG_DIRECTORS\n");
  352. /* Emit initial director header and director code: */
  353. Swig_banner(f_directors_h);
  354. Printf(f_directors_h, "\n");
  355. Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
  356. Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
  357. Printf(f_directors, "\n\n");
  358. Printf(f_directors, "/* ---------------------------------------------------\n");
  359. Printf(f_directors, " * C++ director class methods\n");
  360. Printf(f_directors, " * --------------------------------------------------- */\n\n");
  361. if (outfile_h)
  362. Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
  363. }
  364. Printf(f_runtime, "\n");
  365. Swig_name_register("wrapper", "CSharp_%f");
  366. if (old_variable_names) {
  367. Swig_name_register("set", "set_%n%v");
  368. Swig_name_register("get", "get_%n%v");
  369. }
  370. Printf(f_wrappers, "\n#ifdef __cplusplus\n");
  371. Printf(f_wrappers, "extern \"C\" {\n");
  372. Printf(f_wrappers, "#endif\n\n");
  373. /* Emit code */
  374. Language::top(n);
  375. if (directorsEnabled()) {
  376. // Insert director runtime into the f_runtime file (make it occur before %header section)
  377. Swig_insert_file("director.swg", f_runtime);
  378. }
  379. // Generate the intermediary class
  380. {
  381. String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name);
  382. File *f_im = NewFile(filen, "w", SWIG_output_files());
  383. if (!f_im) {
  384. FileErrorDisplay(filen);
  385. SWIG_exit(EXIT_FAILURE);
  386. }
  387. Append(filenames_list, Copy(filen));
  388. Delete(filen);
  389. filen = NULL;
  390. // Start writing out the intermediary class file
  391. emitBanner(f_im);
  392. addOpenNamespace(0, f_im);
  393. if (imclass_imports)
  394. Printf(f_im, "%s\n", imclass_imports);
  395. if (Len(imclass_class_modifiers) > 0)
  396. Printf(f_im, "%s ", imclass_class_modifiers);
  397. Printf(f_im, "%s ", imclass_name);
  398. if (imclass_baseclass && *Char(imclass_baseclass))
  399. Printf(f_im, ": %s ", imclass_baseclass);
  400. if (Len(imclass_interfaces) > 0)
  401. Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
  402. Printf(f_im, "{\n");
  403. // Add the intermediary class methods
  404. Replaceall(imclass_class_code, "$module", module_class_name);
  405. Replaceall(imclass_class_code, "$imclassname", imclass_name);
  406. Replaceall(imclass_class_code, "$dllimport", dllimport);
  407. Printv(f_im, imclass_class_code, NIL);
  408. Printv(f_im, imclass_cppcasts_code, NIL);
  409. // Finish off the class
  410. Printf(f_im, "}\n");
  411. addCloseNamespace(0, f_im);
  412. Close(f_im);
  413. }
  414. // Generate the C# module class
  415. {
  416. String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name);
  417. File *f_module = NewFile(filen, "w", SWIG_output_files());
  418. if (!f_module) {
  419. FileErrorDisplay(filen);
  420. SWIG_exit(EXIT_FAILURE);
  421. }
  422. Append(filenames_list, Copy(filen));
  423. Delete(filen);
  424. filen = NULL;
  425. // Start writing out the module class file
  426. emitBanner(f_module);
  427. addOpenNamespace(0, f_module);
  428. if (module_imports)
  429. Printf(f_module, "%s\n", module_imports);
  430. if (Len(module_class_modifiers) > 0)
  431. Printf(f_module, "%s ", module_class_modifiers);
  432. Printf(f_module, "%s ", module_class_name);
  433. if (module_baseclass && *Char(module_baseclass))
  434. Printf(f_module, ": %s ", module_baseclass);
  435. if (Len(module_interfaces) > 0)
  436. Printv(f_module, "implements ", module_interfaces, " ", NIL);
  437. Printf(f_module, "{\n");
  438. Replaceall(module_class_code, "$module", module_class_name);
  439. Replaceall(module_class_constants_code, "$module", module_class_name);
  440. Replaceall(module_class_code, "$imclassname", imclass_name);
  441. Replaceall(module_class_constants_code, "$imclassname", imclass_name);
  442. Replaceall(module_class_code, "$dllimport", dllimport);
  443. Replaceall(module_class_constants_code, "$dllimport", dllimport);
  444. // Add the wrapper methods
  445. Printv(f_module, module_class_code, NIL);
  446. // Write out all the global constants
  447. Printv(f_module, module_class_constants_code, NIL);
  448. // Finish off the class
  449. Printf(f_module, "}\n");
  450. addCloseNamespace(0, f_module);
  451. Close(f_module);
  452. }
  453. if (upcasts_code)
  454. Printv(f_wrappers, upcasts_code, NIL);
  455. Printf(f_wrappers, "#ifdef __cplusplus\n");
  456. Printf(f_wrappers, "}\n");
  457. Printf(f_wrappers, "#endif\n");
  458. // Output a C# type wrapper class for each SWIG type
  459. for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
  460. emitTypeWrapperClass(swig_type.key, swig_type.item);
  461. }
  462. // Check for overwriting file problems on filesystems that are case insensitive
  463. Iterator it1;
  464. Iterator it2;
  465. for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
  466. String *item1_lower = Swig_string_lower(it1.item);
  467. for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
  468. String *item2_lower = Swig_string_lower(it2.item);
  469. if (it1.item && it2.item) {
  470. if (Strcmp(item1_lower, item2_lower) == 0) {
  471. Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
  472. "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
  473. "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
  474. }
  475. }
  476. Delete(item2_lower);
  477. }
  478. Delete(item1_lower);
  479. }
  480. Delete(swig_types_hash);
  481. swig_types_hash = NULL;
  482. Delete(filenames_list);
  483. filenames_list = NULL;
  484. Delete(imclass_name);
  485. imclass_name = NULL;
  486. Delete(imclass_class_code);
  487. imclass_class_code = NULL;
  488. Delete(proxy_class_def);
  489. proxy_class_def = NULL;
  490. Delete(proxy_class_code);
  491. proxy_class_code = NULL;
  492. Delete(module_class_constants_code);
  493. module_class_constants_code = NULL;
  494. Delete(imclass_baseclass);
  495. imclass_baseclass = NULL;
  496. Delete(imclass_interfaces);
  497. imclass_interfaces = NULL;
  498. Delete(imclass_class_modifiers);
  499. imclass_class_modifiers = NULL;
  500. Delete(module_class_name);
  501. module_class_name = NULL;
  502. Delete(module_class_code);
  503. module_class_code = NULL;
  504. Delete(module_baseclass);
  505. module_baseclass = NULL;
  506. Delete(module_interfaces);
  507. module_interfaces = NULL;
  508. Delete(module_imports);
  509. module_imports = NULL;
  510. Delete(module_class_modifiers);
  511. module_class_modifiers = NULL;
  512. Delete(imclass_imports);
  513. imclass_imports = NULL;
  514. Delete(imclass_cppcasts_code);
  515. imclass_cppcasts_code = NULL;
  516. Delete(upcasts_code);
  517. upcasts_code = NULL;
  518. Delete(dmethods_seq);
  519. dmethods_seq = NULL;
  520. Delete(dmethods_table);
  521. dmethods_table = NULL;
  522. Delete(namespce);
  523. namespce = NULL;
  524. n_dmethods = 0;
  525. /* Close all of the files */
  526. Dump(f_runtime, f_begin);
  527. Dump(f_header, f_begin);
  528. if (directorsEnabled()) {
  529. Dump(f_directors, f_begin);
  530. Dump(f_directors_h, f_runtime_h);
  531. Printf(f_runtime_h, "\n");
  532. Printf(f_runtime_h, "#endif\n");
  533. Close(f_runtime_h);
  534. Delete(f_runtime_h);
  535. f_runtime_h = NULL;
  536. Delete(f_directors);
  537. f_directors = NULL;
  538. Delete(f_directors_h);
  539. f_directors_h = NULL;
  540. }
  541. Dump(f_wrappers, f_begin);
  542. Wrapper_pretty_print(f_init, f_begin);
  543. Delete(f_header);
  544. Delete(f_wrappers);
  545. Delete(f_init);
  546. Close(f_begin);
  547. Delete(f_runtime);
  548. Delete(f_begin);
  549. return SWIG_OK;
  550. }
  551. /* -----------------------------------------------------------------------------
  552. * emitBanner()
  553. * ----------------------------------------------------------------------------- */
  554. void emitBanner(File *f) {
  555. Printf(f, "/* ----------------------------------------------------------------------------\n");
  556. Swig_banner_target_lang(f, " *");
  557. Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
  558. }
  559. /*-----------------------------------------------------------------------
  560. * Add new director upcall signature
  561. *----------------------------------------------------------------------*/
  562. UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) {
  563. UpcallData *udata;
  564. String *class_methodidx;
  565. Hash *new_udata;
  566. String *key = NewStringf("%s|%s", imclass_method, decl);
  567. ++curr_class_dmethod;
  568. /* Do we know about this director class already? */
  569. if ((udata = Getattr(dmethods_table, key))) {
  570. Delete(key);
  571. return Getattr(udata, "methodoff");
  572. }
  573. class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
  574. n_dmethods++;
  575. new_udata = NewHash();
  576. Append(dmethods_seq, new_udata);
  577. Setattr(dmethods_table, key, new_udata);
  578. Setattr(new_udata, "method", Copy(class_method));
  579. Setattr(new_udata, "class_methodidx", class_methodidx);
  580. Setattr(new_udata, "decl", Copy(decl));
  581. Setattr(new_udata, "overname", Copy(overloaded_name));
  582. Delete(key);
  583. return new_udata;
  584. }
  585. /*-----------------------------------------------------------------------
  586. * Get director upcall signature
  587. *----------------------------------------------------------------------*/
  588. /*
  589. UpcallData * getUpcallMethodData(String *director_class, String *decl) {
  590. String *key = NewStringf("%s|%s", director_class, decl);
  591. UpcallData *udata = Getattr(dmethods_table, key);
  592. Delete(key);
  593. return udata;
  594. }
  595. */
  596. /* ----------------------------------------------------------------------
  597. * nativeWrapper()
  598. * ---------------------------------------------------------------------- */
  599. virtual int nativeWrapper(Node *n) {
  600. String *wrapname = Getattr(n, "wrap:name");
  601. if (!addSymbol(wrapname, n, imclass_name))
  602. return SWIG_ERROR;
  603. if (Getattr(n, "type")) {
  604. Swig_save("nativeWrapper", n, "name", NIL);
  605. Setattr(n, "name", wrapname);
  606. native_function_flag = true;
  607. functionWrapper(n);
  608. Swig_restore(n);
  609. native_function_flag = false;
  610. } else {
  611. Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
  612. }
  613. return SWIG_OK;
  614. }
  615. /* ----------------------------------------------------------------------
  616. * functionWrapper()
  617. * ---------------------------------------------------------------------- */
  618. virtual int functionWrapper(Node *n) {
  619. String *symname = Getattr(n, "sym:name");
  620. SwigType *t = Getattr(n, "type");
  621. ParmList *l = Getattr(n, "parms");
  622. String *tm;
  623. Parm *p;
  624. int i;
  625. String *c_return_type = NewString("");
  626. String *im_return_type = NewString("");
  627. String *cleanup = NewString("");
  628. String *outarg = NewString("");
  629. String *body = NewString("");
  630. String *im_outattributes = 0;
  631. int num_arguments = 0;
  632. bool is_void_return;
  633. String *overloaded_name = getOverloadedName(n);
  634. if (!Getattr(n, "sym:overloaded")) {
  635. if (!addSymbol(Getattr(n, "sym:name"), n, imclass_name))
  636. return SWIG_ERROR;
  637. }
  638. /*
  639. The rest of this function deals with generating the intermediary class wrapper function (that wraps
  640. a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
  641. matching PInvoke c function call.
  642. */
  643. // A new wrapper function object
  644. Wrapper *f = NewWrapper();
  645. // Make a wrapper name for this function
  646. String *wname = Swig_name_wrapper(overloaded_name);
  647. /* Attach the non-standard typemaps to the parameter list. */
  648. Swig_typemap_attach_parms("ctype", l, f);
  649. Swig_typemap_attach_parms("imtype", l, f);
  650. /* Get return types */
  651. if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
  652. String *ctypeout = Getattr(n, "tmap:ctype:out"); // the type in the ctype typemap's out attribute overrides the type in the typemap
  653. if (ctypeout)
  654. tm = ctypeout;
  655. Printf(c_return_type, "%s", tm);
  656. } else {
  657. Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t, 0));
  658. }
  659. if ((tm = Swig_typemap_lookup("imtype", n, "", 0))) {
  660. String *imtypeout = Getattr(n, "tmap:imtype:out"); // the type in the imtype typemap's out attribute overrides the type in the typemap
  661. if (imtypeout)
  662. tm = imtypeout;
  663. Printf(im_return_type, "%s", tm);
  664. im_outattributes = Getattr(n, "tmap:imtype:outattributes");
  665. } else {
  666. Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
  667. }
  668. is_void_return = (Cmp(c_return_type, "void") == 0);
  669. if (!is_void_return)
  670. Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
  671. Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
  672. // Emit all of the local variables for holding arguments.
  673. emit_parameter_variables(l, f);
  674. /* Attach the standard typemaps */
  675. emit_attach_parmmaps(l, f);
  676. // Parameter overloading
  677. Setattr(n, "wrap:parms", l);
  678. Setattr(n, "wrap:name", wname);
  679. // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
  680. if (Getattr(n, "sym:overloaded")) {
  681. // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
  682. Swig_overload_check(n);
  683. if (Getattr(n, "overload:ignore"))
  684. return SWIG_OK;
  685. }
  686. Printv(imclass_class_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
  687. if (im_outattributes)
  688. Printf(imclass_class_code, " %s\n", im_outattributes);
  689. Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name);
  690. /* Get number of required and total arguments */
  691. num_arguments = emit_num_arguments(l);
  692. int gencomma = 0;
  693. // Now walk the function parameter list and generate code to get arguments
  694. for (i = 0, p = l; i < num_arguments; i++) {
  695. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  696. p = Getattr(p, "tmap:in:next");
  697. }
  698. SwigType *pt = Getattr(p, "type");
  699. String *ln = Getattr(p, "lname");
  700. String *im_param_type = NewString("");
  701. String *c_param_type = NewString("");
  702. String *arg = NewString("");
  703. Printf(arg, "j%s", ln);
  704. /* Get the ctype types of the parameter */
  705. if ((tm = Getattr(p, "tmap:ctype"))) {
  706. Printv(c_param_type, tm, NIL);
  707. } else {
  708. Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
  709. }
  710. /* Get the intermediary class parameter types of the parameter */
  711. if ((tm = Getattr(p, "tmap:imtype"))) {
  712. const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
  713. Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
  714. } else {
  715. Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
  716. }
  717. /* Add parameter to intermediary class method */
  718. if (gencomma)
  719. Printf(imclass_class_code, ", ");
  720. Printf(imclass_class_code, "%s %s", im_param_type, arg);
  721. // Add parameter to C function
  722. Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
  723. gencomma = 1;
  724. // Get typemap for this argument
  725. if ((tm = Getattr(p, "tmap:in"))) {
  726. canThrow(n, "in", p);
  727. Replaceall(tm, "$source", arg); /* deprecated */
  728. Replaceall(tm, "$target", ln); /* deprecated */
  729. Replaceall(tm, "$arg", arg); /* deprecated? */
  730. Replaceall(tm, "$input", arg);
  731. Setattr(p, "emit:input", arg);
  732. Printf(f->code, "%s\n", tm);
  733. p = Getattr(p, "tmap:in:next");
  734. } else {
  735. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
  736. p = nextSibling(p);
  737. }
  738. Delete(im_param_type);
  739. Delete(c_param_type);
  740. Delete(arg);
  741. }
  742. /* Insert constraint checking code */
  743. for (p = l; p;) {
  744. if ((tm = Getattr(p, "tmap:check"))) {
  745. canThrow(n, "check", p);
  746. Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
  747. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  748. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  749. Printv(f->code, tm, "\n", NIL);
  750. p = Getattr(p, "tmap:check:next");
  751. } else {
  752. p = nextSibling(p);
  753. }
  754. }
  755. /* Insert cleanup code */
  756. for (p = l; p;) {
  757. if ((tm = Getattr(p, "tmap:freearg"))) {
  758. canThrow(n, "freearg", p);
  759. Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
  760. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  761. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  762. Printv(cleanup, tm, "\n", NIL);
  763. p = Getattr(p, "tmap:freearg:next");
  764. } else {
  765. p = nextSibling(p);
  766. }
  767. }
  768. /* Insert argument output code */
  769. for (p = l; p;) {
  770. if ((tm = Getattr(p, "tmap:argout"))) {
  771. canThrow(n, "argout", p);
  772. Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
  773. Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
  774. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  775. Replaceall(tm, "$result", "jresult");
  776. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  777. Printv(outarg, tm, "\n", NIL);
  778. p = Getattr(p, "tmap:argout:next");
  779. } else {
  780. p = nextSibling(p);
  781. }
  782. }
  783. // Look for usage of throws typemap and the canthrow flag
  784. ParmList *throw_parm_list = NULL;
  785. if ((throw_parm_list = Getattr(n, "catchlist"))) {
  786. Swig_typemap_attach_parms("throws", throw_parm_list, f);
  787. for (p = throw_parm_list; p; p = nextSibling(p)) {
  788. if ((tm = Getattr(p, "tmap:throws"))) {
  789. canThrow(n, "throws", p);
  790. }
  791. }
  792. }
  793. String *null_attribute = 0;
  794. // Now write code to make the function call
  795. if (!native_function_flag) {
  796. if (Cmp(nodeType(n), "constant") == 0) {
  797. // Wrapping a constant hack
  798. Swig_save("functionWrapper", n, "wrap:action", NIL);
  799. // below based on Swig_VargetToFunction()
  800. SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
  801. Setattr(n, "wrap:action", NewStringf("%s = (%s)(%s);", Swig_cresult_name(), SwigType_lstr(ty, 0), Getattr(n, "value")));
  802. }
  803. Swig_director_emit_dynamic_cast(n, f);
  804. String *actioncode = emit_action(n);
  805. if (Cmp(nodeType(n), "constant") == 0)
  806. Swig_restore(n);
  807. /* Return value if necessary */
  808. if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
  809. canThrow(n, "out", n);
  810. Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
  811. Replaceall(tm, "$target", "jresult"); /* deprecated */
  812. Replaceall(tm, "$result", "jresult");
  813. if (GetFlag(n, "feature:new"))
  814. Replaceall(tm, "$owner", "1");
  815. else
  816. Replaceall(tm, "$owner", "0");
  817. Printf(f->code, "%s", tm);
  818. null_attribute = Getattr(n, "tmap:out:null");
  819. if (Len(tm))
  820. Printf(f->code, "\n");
  821. } else {
  822. 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"));
  823. }
  824. emit_return_variable(n, t, f);
  825. }
  826. /* Output argument output code */
  827. Printv(f->code, outarg, NIL);
  828. /* Output cleanup code */
  829. Printv(f->code, cleanup, NIL);
  830. /* Look to see if there is any newfree cleanup code */
  831. if (GetFlag(n, "feature:new")) {
  832. if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
  833. canThrow(n, "newfree", n);
  834. Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
  835. Printf(f->code, "%s\n", tm);
  836. }
  837. }
  838. /* See if there is any return cleanup code */
  839. if (!native_function_flag) {
  840. if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
  841. canThrow(n, "ret", n);
  842. Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
  843. Printf(f->code, "%s\n", tm);
  844. }
  845. }
  846. /* Finish C function and intermediary class function definitions */
  847. Printf(imclass_class_code, ")");
  848. Printf(imclass_class_code, ";\n");
  849. Printf(f->def, ") {");
  850. if (!is_void_return)
  851. Printv(f->code, " return jresult;\n", NIL);
  852. Printf(f->code, "}\n");
  853. /* Substitute the cleanup code */
  854. Replaceall(f->code, "$cleanup", cleanup);
  855. /* Substitute the function name */
  856. Replaceall(f->code, "$symname", symname);
  857. /* Contract macro modification */
  858. if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
  859. Setattr(n, "csharp:canthrow", "1");
  860. }
  861. if (!null_attribute)
  862. Replaceall(f->code, "$null", "0");
  863. else
  864. Replaceall(f->code, "$null", null_attribute);
  865. /* Dump the function out */
  866. if (!native_function_flag) {
  867. Wrapper_print(f, f_wrappers);
  868. // Handle %csexception which sets the canthrow attribute
  869. if (Getattr(n, "feature:except:canthrow"))
  870. Setattr(n, "csharp:canthrow", "1");
  871. // A very simple check (it is not foolproof) to help typemap/feature writers for
  872. // throwing C# exceptions from unmanaged code. It checks for the common methods which
  873. // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set
  874. // so that code which checks for pending exceptions is added in the C# proxy method.
  875. if (!Getattr(n, "csharp:canthrow")) {
  876. if (Strstr(f->code, "SWIG_exception")) {
  877. Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
  878. "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n");
  879. } else if (Strstr(f->code, "SWIG_CSharpSetPendingException")) {
  880. Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
  881. "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n");
  882. }
  883. }
  884. }
  885. if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
  886. moduleClassFunctionHandler(n);
  887. }
  888. /*
  889. * Generate the proxy class properties for public member variables.
  890. * Not for enums and constants.
  891. */
  892. if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
  893. // Capitalize the first letter in the variable in the getter/setter function name
  894. bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, proxy_class_name, variable_name))) != 0;
  895. String *getter_setter_name = NewString("");
  896. if (!getter_flag)
  897. Printf(getter_setter_name, "set");
  898. else
  899. Printf(getter_setter_name, "get");
  900. Putc(toupper((int) *Char(variable_name)), getter_setter_name);
  901. Printf(getter_setter_name, "%s", Char(variable_name) + 1);
  902. Setattr(n, "proxyfuncname", getter_setter_name);
  903. Setattr(n, "imfuncname", symname);
  904. proxyClassFunctionHandler(n);
  905. Delete(getter_setter_name);
  906. }
  907. Delete(c_return_type);
  908. Delete(im_return_type);
  909. Delete(cleanup);
  910. Delete(outarg);
  911. Delete(body);
  912. Delete(overloaded_name);
  913. DelWrapper(f);
  914. return SWIG_OK;
  915. }
  916. /* -----------------------------------------------------------------------
  917. * variableWrapper()
  918. * ----------------------------------------------------------------------- */
  919. virtual int variableWrapper(Node *n) {
  920. Language::variableWrapper(n);
  921. return SWIG_OK;
  922. }
  923. /* -----------------------------------------------------------------------
  924. * globalvariableHandler()
  925. * ------------------------------------------------------------------------ */
  926. virtual int globalvariableHandler(Node *n) {
  927. generate_property_declaration_flag = true;
  928. variable_name = Getattr(n, "sym:name");
  929. global_variable_flag = true;
  930. int ret = Language::globalvariableHandler(n);
  931. global_variable_flag = false;
  932. generate_property_declaration_flag = false;
  933. if (proxy_flag) {
  934. Printf(module_class_code, "\n }\n\n");
  935. }
  936. return ret;
  937. }
  938. /* ----------------------------------------------------------------------
  939. * enumDeclaration()
  940. *
  941. * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
  942. * 1) Simple enums - simple constant within the proxy class or module class
  943. * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
  944. * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
  945. * 4) Proper enums - proper C# enum
  946. * Anonymous enums always default to 1)
  947. * ---------------------------------------------------------------------- */
  948. virtual int enumDeclaration(Node *n) {
  949. if (!ImportMode) {
  950. if (getCurrentClass() && (cplus_mode != PUBLIC))
  951. return SWIG_NOWRAP;
  952. String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
  953. if (proxy_flag && !is_wrapping_class()) {
  954. // Global enums / enums in a namespace
  955. assert(!full_imclass_name);
  956. if (!nspace) {
  957. full_imclass_name = NewStringf("%s", imclass_name);
  958. } else {
  959. if (namespce) {
  960. full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
  961. } else {
  962. full_imclass_name = NewStringf("%s", imclass_name);
  963. }
  964. }
  965. }
  966. enum_code = NewString("");
  967. String *symname = Getattr(n, "sym:name");
  968. String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
  969. EnumFeature enum_feature = decodeEnumFeature(n);
  970. String *typemap_lookup_type = Getattr(n, "name");
  971. if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
  972. // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
  973. String *scope = 0;
  974. if (nspace || proxy_class_name) {
  975. scope = NewString("");
  976. if (nspace)
  977. Printf(scope, "%s", nspace);
  978. if (proxy_class_name)
  979. Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
  980. }
  981. if (!addSymbol(symname, n, scope))
  982. return SWIG_ERROR;
  983. // Pure C# baseclass and interfaces
  984. const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE);
  985. const String *pure_interfaces = typemapLookup(n, "csinterfaces", typemap_lookup_type, WARN_NONE);
  986. // Class attributes
  987. const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
  988. if (csattributes && *Char(csattributes))
  989. Printf(enum_code, "%s\n", csattributes);
  990. // Emit the enum
  991. Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
  992. " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
  993. ", " : "", pure_interfaces, " {\n", NIL);
  994. Delete(scope);
  995. } else {
  996. // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
  997. if (symname && !Getattr(n, "unnamedinstance"))
  998. Printf(constants_code, " // %s \n", symname);
  999. }
  1000. // Emit each enum item
  1001. Language::enumDeclaration(n);
  1002. if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
  1003. // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
  1004. // Finish the enum declaration
  1005. // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
  1006. Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
  1007. typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
  1008. "}", NIL);
  1009. Replaceall(enum_code, "$csclassname", symname);
  1010. // Substitute $enumvalues - intended usage is for typesafe enums
  1011. if (Getattr(n, "enumvalues"))
  1012. Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
  1013. else
  1014. Replaceall(enum_code, "$enumvalues", "");
  1015. if (proxy_flag && is_wrapping_class()) {
  1016. // Enums defined within the C++ class are defined within the proxy class
  1017. // Add extra indentation
  1018. Replaceall(enum_code, "\n", "\n ");
  1019. Replaceall(enum_code, " \n", "\n");
  1020. Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
  1021. } else {
  1022. // Global enums are defined in their own file
  1023. String *output_directory = outputDirectory(nspace);
  1024. String *filen = NewStringf("%s%s.cs", output_directory, symname);
  1025. File *f_enum = NewFile(filen, "w", SWIG_output_files());
  1026. if (!f_enum) {
  1027. FileErrorDisplay(filen);
  1028. SWIG_exit(EXIT_FAILURE);
  1029. }
  1030. Append(filenames_list, Copy(filen));
  1031. Delete(filen);
  1032. filen = NULL;
  1033. // Start writing out the enum file
  1034. emitBanner(f_enum);
  1035. addOpenNamespace(nspace, f_enum);
  1036. Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
  1037. "\n", enum_code, "\n", NIL);
  1038. addCloseNamespace(nspace, f_enum);
  1039. Close(f_enum);
  1040. Delete(output_directory);
  1041. }
  1042. } else {
  1043. // Wrap C++ enum with simple constant
  1044. Printf(enum_code, "\n");
  1045. if (proxy_flag && is_wrapping_class())
  1046. Printv(proxy_class_constants_code, enum_code, NIL);
  1047. else
  1048. Printv(module_class_constants_code, enum_code, NIL);
  1049. }
  1050. Delete(enum_code);
  1051. enum_code = NULL;
  1052. if (proxy_flag && !is_wrapping_class()) {
  1053. Delete(full_imclass_name);
  1054. full_imclass_name = 0;
  1055. }
  1056. }
  1057. return SWIG_OK;
  1058. }
  1059. /* ----------------------------------------------------------------------
  1060. * enumvalueDeclaration()
  1061. * ---------------------------------------------------------------------- */
  1062. virtual int enumvalueDeclaration(Node *n) {
  1063. if (getCurrentClass() && (cplus_mode != PUBLIC))
  1064. return SWIG_NOWRAP;
  1065. Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
  1066. String *symname = Getattr(n, "sym:name");
  1067. String *value = Getattr(n, "value");
  1068. String *name = Getattr(n, "name");
  1069. Node *parent = parentNode(n);
  1070. int unnamedinstance = GetFlag(parent, "unnamedinstance");
  1071. String *parent_name = Getattr(parent, "name");
  1072. String *nspace = getNSpace();
  1073. String *tmpValue;
  1074. // Strange hack from parent method
  1075. if (value)
  1076. tmpValue = NewString(value);
  1077. else
  1078. tmpValue = NewString(name);
  1079. // Note that this is used in enumValue() amongst other places
  1080. Setattr(n, "value", tmpValue);
  1081. // Deal with enum values that are not int
  1082. int swigtype = SwigType_type(Getattr(n, "type"));
  1083. if (swigtype == T_BOOL) {
  1084. const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
  1085. Setattr(n, "enumvalue", val);
  1086. } else if (swigtype == T_CHAR) {
  1087. String *val = NewStringf("'%s'", Getattr(n, "enumvalue"));
  1088. Setattr(n, "enumvalue", val);
  1089. Delete(val);
  1090. }
  1091. {
  1092. EnumFeature enum_feature = decodeEnumFeature(parent);
  1093. // Add to language symbol table
  1094. String *scope = 0;
  1095. if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
  1096. if (proxy_class_name) {
  1097. scope = NewString("");
  1098. if (nspace)
  1099. Printf(scope, "%s.", nspace);
  1100. Printf(scope, "%s", proxy_class_name);
  1101. } else {
  1102. scope = Copy(module_class_name);
  1103. }
  1104. } else {
  1105. scope = NewString("");
  1106. if (nspace)
  1107. Printf(scope, "%s.", nspace);
  1108. if (proxy_class_name)
  1109. Printf(scope, "%s.", proxy_class_name);
  1110. Printf(scope, "%s",Getattr(parent, "sym:name"));
  1111. }
  1112. if (!addSymbol(name, n, scope))
  1113. return SWIG_ERROR;
  1114. const String *csattributes = Getattr(n, "feature:cs:attributes");
  1115. if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
  1116. // Wrap (non-anonymous) C/C++ enum with a proper C# enum
  1117. // Emit the enum item.
  1118. if (!GetFlag(n, "firstenumitem"))
  1119. Printf(enum_code, ",\n");
  1120. if (csattributes)
  1121. Printf(enum_code, " %s\n", csattributes);
  1122. Printf(enum_code, " %s", symname);
  1123. // Check for the %csconstvalue feature
  1124. String *value = Getattr(n, "feature:cs:constvalue");
  1125. // Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
  1126. value = value ? value : Getattr(n, "enumvalue");
  1127. if (value) {
  1128. Printf(enum_code, " = %s", value);
  1129. }
  1130. } else {
  1131. // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
  1132. SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
  1133. Setattr(n, "type", typemap_lookup_type);
  1134. const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF);
  1135. String *return_type = Copy(tm);
  1136. substituteClassname(typemap_lookup_type, return_type);
  1137. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  1138. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  1139. if (csattributes)
  1140. Printf(enum_code, " %s\n", csattributes);
  1141. if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
  1142. // Wrap (non-anonymous) enum using the typesafe enum pattern
  1143. if (Getattr(n, "enumvalue")) {
  1144. String *value = enumValue(n);
  1145. Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
  1146. Delete(value);
  1147. } else {
  1148. Printf(enum_code, " %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
  1149. }
  1150. } else {
  1151. // Simple integer constants
  1152. // Note these are always generated for anonymous enums, no matter what enum_feature is specified
  1153. // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
  1154. // The %csconst feature determines how the constant value is obtained
  1155. int const_feature_flag = GetFlag(n, "feature:cs:const");
  1156. const char *const_readonly = const_feature_flag ? "const" : "static readonly";
  1157. String *value = enumValue(n);
  1158. Printf(enum_code, " %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value);
  1159. Delete(value);
  1160. }
  1161. Delete(return_type);
  1162. }
  1163. // Add the enum value to the comma separated list being constructed in the enum declaration.
  1164. String *enumvalues = Getattr(parent, "enumvalues");
  1165. if (!enumvalues)
  1166. Setattr(parent, "enumvalues", Copy(symname));
  1167. else
  1168. Printv(enumvalues, ", ", symname, NIL);
  1169. Delete(scope);
  1170. }
  1171. Delete(tmpValue);
  1172. Swig_restore(n);
  1173. return SWIG_OK;
  1174. }
  1175. /* -----------------------------------------------------------------------
  1176. * constantWrapper()
  1177. * Used for wrapping constants - #define or %constant.
  1178. * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
  1179. * C# static const variables are generated for these.
  1180. * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
  1181. * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
  1182. * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
  1183. * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
  1184. * ------------------------------------------------------------------------ */
  1185. virtual int constantWrapper(Node *n) {
  1186. String *symname = Getattr(n, "sym:name");
  1187. SwigType *t = Getattr(n, "type");
  1188. ParmList *l = Getattr(n, "parms");
  1189. String *tm;
  1190. String *return_type = NewString("");
  1191. String *constants_code = NewString("");
  1192. Swig_save("constantWrapper", n, "value", NIL);
  1193. Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:cstype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:cstype:outattributes", NIL);
  1194. bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
  1195. const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
  1196. if (!is_enum_item) {
  1197. String *scope = 0;
  1198. if (proxy_class_name) {
  1199. String *nspace = getNSpace();
  1200. scope = NewString("");
  1201. if (nspace)
  1202. Printf(scope, "%s.", nspace);
  1203. Printf(scope, "%s", proxy_class_name);
  1204. } else {
  1205. scope = Copy(module_class_name);
  1206. }
  1207. if (!addSymbol(itemname, n, scope))
  1208. return SWIG_ERROR;
  1209. Delete(scope);
  1210. }
  1211. // The %csconst feature determines how the constant value is obtained
  1212. int const_feature_flag = GetFlag(n, "feature:cs:const");
  1213. /* Adjust the enum type for the Swig_typemap_lookup.
  1214. * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
  1215. if (is_enum_item) {
  1216. t = Getattr(parentNode(n), "enumtype");
  1217. Setattr(n, "type", t);
  1218. }
  1219. /* Attach the non-standard typemaps to the parameter list. */
  1220. Swig_typemap_attach_parms("cstype", l, NULL);
  1221. /* Get C# return types */
  1222. bool classname_substituted_flag = false;
  1223. if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
  1224. String *cstypeout = Getattr(n, "tmap:cstype:out"); // the type in the cstype typemap's out attribute overrides the type in the typemap
  1225. if (cstypeout)
  1226. tm = cstypeout;
  1227. classname_substituted_flag = substituteClassname(t, tm);
  1228. Printf(return_type, "%s", tm);
  1229. } else {
  1230. Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
  1231. }
  1232. // Add the stripped quotes back in
  1233. String *new_value = NewString("");
  1234. if (SwigType_type(t) == T_STRING) {
  1235. Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
  1236. Setattr(n, "value", new_value);
  1237. } else if (SwigType_type(t) == T_CHAR) {
  1238. Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
  1239. Setattr(n, "value", new_value);
  1240. }
  1241. const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
  1242. if (outattributes)
  1243. Printf(constants_code, " %s\n", outattributes);
  1244. const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
  1245. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  1246. Printf(constants_code, " %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname);
  1247. // Check for the %csconstvalue feature
  1248. String *value = Getattr(n, "feature:cs:constvalue");
  1249. if (value) {
  1250. Printf(constants_code, "%s;\n", value);
  1251. } else if (!const_feature_flag) {
  1252. // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call.
  1253. if (classname_substituted_flag) {
  1254. if (SwigType_isenum(t)) {
  1255. // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
  1256. Printf(constants_code, "(%s)%s.%s();\n", return_type, full_imclass_name, Swig_name_get(getNSpace(), symname));
  1257. } else {
  1258. // This handles function pointers using the %constant directive
  1259. Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1260. }
  1261. } else {
  1262. Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
  1263. }
  1264. // Each constant and enum value is wrapped with a separate PInvoke function call
  1265. SetFlag(n, "feature:immutable");
  1266. enum_constant_flag = true;
  1267. variableWrapper(n);
  1268. enum_constant_flag = false;
  1269. } else {
  1270. // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
  1271. if (Getattr(n, "wrappedasconstant")) {
  1272. if (SwigType_type(t) == T_CHAR)
  1273. Printf(constants_code, "\'%s\';\n", Getattr(n, "staticmembervariableHandler:value"));
  1274. else
  1275. Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
  1276. } else {
  1277. Printf(constants_code, "%s;\n", Getattr(n, "value"));
  1278. }
  1279. }
  1280. // Emit the generated code to appropriate place
  1281. // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed
  1282. if (!is_enum_item) {
  1283. if (proxy_flag && wrapping_member_flag)
  1284. Printv(proxy_class_constants_code, constants_code, NIL);
  1285. else
  1286. Printv(module_class_constants_code, constants_code, NIL);
  1287. }
  1288. // Cleanup
  1289. Swig_restore(n);
  1290. Delete(new_value);
  1291. Delete(return_type);
  1292. Delete(constants_code);
  1293. return SWIG_OK;
  1294. }
  1295. /* -----------------------------------------------------------------------------
  1296. * insertDirective()
  1297. * ----------------------------------------------------------------------------- */
  1298. virtual int insertDirective(Node *n) {
  1299. String *code = Getattr(n, "code");
  1300. Replaceall(code, "$module", module_class_name);
  1301. Replaceall(code, "$imclassname", imclass_name);
  1302. Replaceall(code, "$dllimport", dllimport);
  1303. return Language::insertDirective(n);
  1304. }
  1305. /* -----------------------------------------------------------------------------
  1306. * pragmaDirective()
  1307. *
  1308. * Valid Pragmas:
  1309. * imclassbase - base (extends) for the intermediary class
  1310. * imclassclassmodifiers - class modifiers for the intermediary class
  1311. * imclasscode - text (C# code) is copied verbatim to the intermediary class
  1312. * imclassimports - import statements for the intermediary class
  1313. * imclassinterfaces - interface (implements) for the intermediary class
  1314. *
  1315. * modulebase - base (extends) for the module class
  1316. * moduleclassmodifiers - class modifiers for the module class
  1317. * modulecode - text (C# code) is copied verbatim to the module class
  1318. * moduleimports - import statements for the module class
  1319. * moduleinterfaces - interface (implements) for the module class
  1320. *
  1321. * ----------------------------------------------------------------------------- */
  1322. virtual int pragmaDirective(Node *n) {
  1323. if (!ImportMode) {
  1324. String *lang = Getattr(n, "lang");
  1325. String *code = Getattr(n, "name");
  1326. String *value = Getattr(n, "value");
  1327. if (Strcmp(lang, "csharp") == 0) {
  1328. String *strvalue = NewString(value);
  1329. Replaceall(strvalue, "\\\"", "\"");
  1330. if (Strcmp(code, "imclassbase") == 0) {
  1331. Delete(imclass_baseclass);
  1332. imclass_baseclass = Copy(strvalue);
  1333. } else if (Strcmp(code, "imclassclassmodifiers") == 0) {
  1334. Delete(imclass_class_modifiers);
  1335. imclass_class_modifiers = Copy(strvalue);
  1336. } else if (Strcmp(code, "imclasscode") == 0) {
  1337. Printf(imclass_class_code, "%s\n", strvalue);
  1338. } else if (Strcmp(code, "imclassimports") == 0) {
  1339. Delete(imclass_imports);
  1340. imclass_imports = Copy(strvalue);
  1341. } else if (Strcmp(code, "imclassinterfaces") == 0) {
  1342. Delete(imclass_interfaces);
  1343. imclass_interfaces = Copy(strvalue);
  1344. } else if (Strcmp(code, "modulebase") == 0) {
  1345. Delete(module_baseclass);
  1346. module_baseclass = Copy(strvalue);
  1347. } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
  1348. Delete(module_class_modifiers);
  1349. module_class_modifiers = Copy(strvalue);
  1350. } else if (Strcmp(code, "modulecode") == 0) {
  1351. Printf(module_class_code, "%s\n", strvalue);
  1352. } else if (Strcmp(code, "moduleimports") == 0) {
  1353. Delete(module_imports);
  1354. module_imports = Copy(strvalue);
  1355. } else if (Strcmp(code, "moduleinterfaces") == 0) {
  1356. Delete(module_interfaces);
  1357. module_interfaces = Copy(strvalue);
  1358. } else {
  1359. Swig_error(input_file, line_number, "Unrecognized pragma.\n");
  1360. }
  1361. Delete(strvalue);
  1362. }
  1363. }
  1364. return Language::pragmaDirective(n);
  1365. }
  1366. /* -----------------------------------------------------------------------------
  1367. * emitProxyClassDefAndCPPCasts()
  1368. * ----------------------------------------------------------------------------- */
  1369. void emitProxyClassDefAndCPPCasts(Node *n) {
  1370. String *c_classname = SwigType_namestr(Getattr(n, "name"));
  1371. String *c_baseclass = NULL;
  1372. String *baseclass = NULL;
  1373. String *c_baseclassname = NULL;
  1374. SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
  1375. bool feature_director = Swig_directorclass(n) ? true : false;
  1376. // Inheritance from pure C# classes
  1377. Node *attributes = NewHash();
  1378. const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
  1379. bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
  1380. bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
  1381. Delete(attributes);
  1382. // C++ inheritance
  1383. if (!purebase_replace) {
  1384. List *baselist = Getattr(n, "bases");
  1385. if (baselist) {
  1386. Iterator base = First(baselist);
  1387. while (base.item && GetFlag(base.item, "feature:ignore")) {
  1388. base = Next(base);
  1389. }
  1390. if (base.item) {
  1391. c_baseclassname = Getattr(base.item, "name");
  1392. baseclass = Copy(getProxyName(c_baseclassname));
  1393. if (baseclass)
  1394. c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
  1395. base = Next(base);
  1396. /* Warn about multiple inheritance for additional base class(es) */
  1397. while (base.item) {
  1398. if (GetFlag(base.item, "feature:ignore")) {
  1399. base = Next(base);
  1400. continue;
  1401. }
  1402. String *proxyclassname = Getattr(n, "classtypeobj");
  1403. String *baseclassname = Getattr(base.item, "name");
  1404. Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
  1405. "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
  1406. base = Next(base);
  1407. }
  1408. }
  1409. }
  1410. }
  1411. bool derived = baseclass && getProxyName(c_baseclassname);
  1412. if (derived && purebase_notderived)
  1413. pure_baseclass = empty_string;
  1414. const String *wanted_base = baseclass ? baseclass : pure_baseclass;
  1415. if (purebase_replace) {
  1416. wanted_base = pure_baseclass;
  1417. derived = false;
  1418. Delete(baseclass);
  1419. baseclass = NULL;
  1420. if (purebase_notderived)
  1421. Swig_error(Getfile(n), Getline(n), "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
  1422. } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
  1423. Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
  1424. "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#. "
  1425. "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
  1426. }
  1427. // Pure C# interfaces
  1428. const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
  1429. // Start writing the proxy class
  1430. Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
  1431. "\n", NIL);
  1432. // Class attributes
  1433. const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
  1434. if (csattributes && *Char(csattributes))
  1435. Printf(proxy_class_def, "%s\n", csattributes);
  1436. Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
  1437. " $csclassname", // Class name and base class
  1438. (*Char(wanted_base) || *Char(pure_interfaces)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(pure_interfaces)) ? // Interfaces
  1439. ", " : "", pure_interfaces, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
  1440. typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
  1441. NIL);
  1442. // C++ destructor is wrapped by the Dispose method
  1443. // Note that the method name is specified in a typemap attribute called methodname
  1444. String *destruct = NewString("");
  1445. const String *tm = NULL;
  1446. attributes = NewHash();
  1447. String *destruct_methodname = NULL;
  1448. String *destruct_methodmodifiers = NULL;
  1449. if (derived) {
  1450. tm = typemapLookup(n, "csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
  1451. destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname");
  1452. destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct_derived:methodmodifiers");
  1453. } else {
  1454. tm = typemapLookup(n, "csdestruct", typemap_lookup_type, WARN_NONE, attributes);
  1455. destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname");
  1456. destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct:methodmodifiers");
  1457. }
  1458. if (tm && *Char(tm)) {
  1459. if (!destruct_methodname) {
  1460. Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
  1461. }
  1462. if (!destruct_methodmodifiers) {
  1463. Swig_error(Getfile(n), Getline(n),
  1464. "No methodmodifiers attribute defined in csdestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
  1465. }
  1466. }
  1467. // Emit the Finalize and Dispose methods
  1468. if (tm) {
  1469. // Finalize method
  1470. if (*Char(destructor_call)) {
  1471. Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL);
  1472. }
  1473. // Dispose method
  1474. Printv(destruct, tm, NIL);
  1475. if (*Char(destructor_call))
  1476. Replaceall(destruct, "$imcall", destructor_call);
  1477. else
  1478. Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
  1479. if (*Char(destruct))
  1480. Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n",
  1481. NIL);
  1482. }
  1483. if (feature_director) {
  1484. // Generate director connect method
  1485. // put this in classDirectorEnd ???
  1486. Printf(proxy_class_code, " private void SwigDirectorConnect() {\n");
  1487. int i;
  1488. for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  1489. UpcallData *udata = Getitem(dmethods_seq, i);
  1490. String *method = Getattr(udata, "method");
  1491. String *methid = Getattr(udata, "class_methodidx");
  1492. String *overname = Getattr(udata, "overname");
  1493. Printf(proxy_class_code, " if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
  1494. Printf(proxy_class_code, " swigDelegate%s = new SwigDelegate%s_%s(SwigDirector%s);\n", methid, proxy_class_name, methid, overname);
  1495. }
  1496. String *director_connect_method_name = Swig_name_member(getNSpace(), proxy_class_name, "director_connect");
  1497. Printf(proxy_class_code, " %s.%s(swigCPtr", imclass_name, director_connect_method_name);
  1498. for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
  1499. UpcallData *udata = Getitem(dmethods_seq, i);
  1500. String *methid = Getattr(udata, "class_methodidx");
  1501. Printf(proxy_class_code, ", swigDelegate%s", methid);
  1502. }
  1503. Printf(proxy_class_code, ");\n");
  1504. Printf(proxy_class_code, " }\n");
  1505. if (first_class_dmethod < curr_class_dmethod) {
  1506. // Only emit if there is at least one director method
  1507. Printf(proxy_class_code, "\n");
  1508. Printf(proxy_class_code, " private bool SwigDerivedClassHasMethod(string methodName, Type[] methodTypes) {\n");
  1509. Printf(proxy_class_code,
  1510. " System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, methodTypes, null);\n");
  1511. Printf(proxy_class_code, " bool