/tags/rel-1-3-24/SWIG/Source/Modules/csharp.cxx
C++ | 1776 lines | 1226 code | 293 blank | 257 comment | 298 complexity | aea27b8ea2204f0bf252365dcfba5a3f MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
1/* -----------------------------------------------------------------------------
2 * csharp.cxx
3 *
4 * CSharp wrapper module.
5 *
6 * Author(s) : William Fulton
7 * Neil Cawse
8 *
9 * Copyright (C) 1999-2002. The University of Chicago
10 * See the file LICENSE for information on usage and redistribution.
11 * ----------------------------------------------------------------------------- */
12
13char cvsroot_csharp_cxx[] = "$Header$";
14
15#include <limits.h> // for INT_MAX
16#include "swigmod.h"
17#include <ctype.h>
18
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_runtime;
28 File *f_header;
29 File *f_wrappers;
30 File *f_init;
31
32 bool proxy_flag; // Flag for generating proxy classes
33 bool have_default_constructor_flag;
34 bool native_function_flag; // Flag for when wrapping a native function
35 bool enum_constant_flag; // Flag for when wrapping an enum or constant
36 bool static_flag; // Flag for when wrapping a static functions or member variables
37 bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
38 bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
39 bool global_variable_flag; // Flag for when wrapping a global variable
40
41 String *imclass_name; // intermediary class name
42 String *module_class_name; // module class name
43 String *imclass_class_code; // intermediary class code
44 String *proxy_class_def;
45 String *proxy_class_code;
46 String *module_class_code;
47 String *proxy_class_name;
48 String *variable_name; //Name of a variable being wrapped
49 String *proxy_class_constants_code;
50 String *module_class_constants_code;
51 String *enum_code;
52 String *dllimport; // DllImport attribute name
53 String *namespce; // Optional namespace name
54 String *imclass_imports; //intermediary class imports from %pragma
55 String *module_imports; //module imports from %pragma
56 String *imclass_baseclass; //inheritance for intermediary class class from %pragma
57 String *module_baseclass; //inheritance for module class from %pragma
58 String *imclass_interfaces; //interfaces for intermediary class class from %pragma
59 String *module_interfaces; //interfaces for module class from %pragma
60 String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma
61 String *module_class_modifiers; //class modifiers for module class overriden by %pragma
62 String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
63 String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
64 String *destructor_call; //C++ destructor call if any
65
66 enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
67
68 public:
69
70 /* -----------------------------------------------------------------------------
71 * CSHARP()
72 * ----------------------------------------------------------------------------- */
73
74 CSHARP() :
75 empty_string(NewString("")),
76 public_string(NewString("public")),
77 protected_string(NewString("protected")),
78
79 swig_types_hash(NULL),
80 f_runtime(NULL),
81 f_header(NULL),
82 f_wrappers(NULL),
83 f_init(NULL),
84
85 proxy_flag(true),
86 have_default_constructor_flag(false),
87 native_function_flag(false),
88 enum_constant_flag(false),
89 static_flag(false),
90 variable_wrapper_flag(false),
91 wrapping_member_flag(false),
92 global_variable_flag(false),
93
94 imclass_name(NULL),
95 module_class_name(NULL),
96 imclass_class_code(NULL),
97 proxy_class_def(NULL),
98 proxy_class_code(NULL),
99 module_class_code(NULL),
100 proxy_class_name(NULL),
101 variable_name(NULL),
102 proxy_class_constants_code(NULL),
103 module_class_constants_code(NULL),
104 enum_code(NULL),
105 dllimport(NULL),
106 namespce(NULL),
107 imclass_imports(NULL),
108 module_imports(NULL),
109 imclass_baseclass(NULL),
110 module_baseclass(NULL),
111 imclass_interfaces(NULL),
112 module_interfaces(NULL),
113 imclass_class_modifiers(NULL),
114 module_class_modifiers(NULL),
115 upcasts_code(NULL),
116 imclass_cppcasts_code(NULL),
117 destructor_call(NULL)
118
119 {
120 }
121
122 /* -----------------------------------------------------------------------------
123 * getProxyName()
124 *
125 * Test to see if a type corresponds to something wrapped with a proxy class
126 * Return NULL if not otherwise the proxy class name
127 * ----------------------------------------------------------------------------- */
128
129 String *getProxyName(SwigType *t) {
130 if (proxy_flag) {
131 Node *n = classLookup(t);
132 if (n) {
133 return Getattr(n,"sym:name");
134 }
135 }
136 return NULL;
137 }
138
139 /* ------------------------------------------------------------
140 * main()
141 * ------------------------------------------------------------ */
142
143 virtual void main(int argc, char *argv[]) {
144
145 SWIG_library_directory("csharp");
146
147 // Look for certain command line options
148 for (int i = 1; i < argc; i++) {
149 if (argv[i]) {
150 if (strcmp(argv[i],"-dllimport") == 0) {
151 if (argv[i+1]) {
152 dllimport = NewString("");
153 Printf(dllimport, argv[i+1]);
154 Swig_mark_arg(i);
155 Swig_mark_arg(i+1);
156 i++;
157 } else {
158 Swig_arg_error();
159 }
160 } else if (strcmp(argv[i],"-namespace") == 0) {
161 if (argv[i+1]) {
162 namespce = NewString("");
163 Printf(namespce, argv[i+1]);
164 Swig_mark_arg(i);
165 Swig_mark_arg(i+1);
166 i++;
167 } else {
168 Swig_arg_error();
169 }
170 } else if ((strcmp(argv[i],"-noproxy") == 0)) {
171 Swig_mark_arg(i);
172 proxy_flag = false;
173 } else if (strcmp(argv[i],"-help") == 0) {
174 Printf(stderr,"%s\n", usage);
175 }
176 }
177 }
178
179 // Add a symbol to the parser for conditional compilation
180 Preprocessor_define("SWIGCSHARP 1",0);
181
182 // Add typemap definitions
183 SWIG_typemap_lang("csharp");
184 SWIG_config_file("csharp.swg");
185
186 allow_overloading();
187 }
188
189 /* ---------------------------------------------------------------------
190 * top()
191 * --------------------------------------------------------------------- */
192
193 virtual int top(Node *n) {
194
195 // Get any options set in the module directive
196 Node* optionsnode = Getattr( Getattr(n,"module"), "options");
197
198 if (optionsnode) {
199 if (Getattr(optionsnode,"imclassname"))
200 imclass_name = Copy(Getattr(optionsnode,"imclassname"));
201 }
202
203 /* Initialize all of the output files */
204 String *outfile = Getattr(n,"outfile");
205
206 f_runtime = NewFile(outfile,"w");
207 if (!f_runtime) {
208 Printf(stderr,"Unable to open %s\n", outfile);
209 SWIG_exit(EXIT_FAILURE);
210 }
211 f_init = NewString("");
212 f_header = NewString("");
213 f_wrappers = NewString("");
214
215 /* Register file targets with the SWIG file handler */
216 Swig_register_filebyname("header",f_header);
217 Swig_register_filebyname("wrapper",f_wrappers);
218 Swig_register_filebyname("runtime",f_runtime);
219 Swig_register_filebyname("init",f_init);
220
221 swig_types_hash = NewHash();
222
223 // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
224 if (!imclass_name) {
225 imclass_name = NewStringf("%sPINVOKE", Getattr(n,"name"));
226 module_class_name = Copy(Getattr(n,"name"));
227 } else {
228 // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
229 if (Cmp(imclass_name, Getattr(n,"name")) == 0)
230 module_class_name = NewStringf("%sModule", Getattr(n,"name"));
231 else
232 module_class_name = Copy(Getattr(n,"name"));
233 }
234
235 imclass_class_code = NewString("");
236 proxy_class_def = NewString("");
237 proxy_class_code = NewString("");
238 module_class_constants_code = NewString("");
239 imclass_baseclass = NewString("");
240 imclass_interfaces = NewString("");
241 imclass_class_modifiers = NewString("");
242 module_class_code = NewString("");
243 module_baseclass = NewString("");
244 module_interfaces = NewString("");
245 module_imports = NewString("");
246 module_class_modifiers = NewString("");
247 imclass_imports = NewString("");
248 imclass_cppcasts_code = NewString("");
249 upcasts_code = NewString("");
250 if (!namespce) namespce = NewString("");
251 if (!dllimport) dllimport = Copy(module_class_name);
252
253 Swig_banner(f_runtime); // Print the SWIG banner message
254
255 String *wrapper_name = NewString("");
256
257 Printf(wrapper_name, "CSharp_%%f", imclass_name);
258 Swig_name_register((char*)"wrapper", Char(wrapper_name));
259 Swig_name_register((char*)"set", (char*)"set_%v");
260 Swig_name_register((char*)"get", (char*)"get_%v");
261 Swig_name_register((char*)"member", (char*)"%c_%m");
262
263 Delete(wrapper_name);
264
265 Printf(f_wrappers,"\n#ifdef __cplusplus\n");
266 Printf(f_wrappers,"extern \"C\" {\n");
267 Printf(f_wrappers,"#endif\n\n");
268
269 /* Emit code */
270 Language::top(n);
271
272 // Generate the intermediary class
273 {
274 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name);
275 File *f_im = NewFile(filen,"w");
276 if(!f_im) {
277 Printf(stderr,"Unable to open %s\n", filen);
278 SWIG_exit(EXIT_FAILURE);
279 }
280 Delete(filen); filen = NULL;
281
282 // Start writing out the intermediary class file
283 emitBanner(f_im);
284
285 if(Len(namespce) > 0)
286 Printf(f_im, "namespace %s {\n", namespce);
287
288 if(imclass_imports)
289 Printf(f_im, "%s\n", imclass_imports);
290
291 if (Len(imclass_class_modifiers) > 0)
292 Printf(f_im, "%s ", imclass_class_modifiers);
293 Printf(f_im, "%s ", imclass_name);
294
295 if (imclass_baseclass && *Char(imclass_baseclass))
296 Printf(f_im, ": %s ", imclass_baseclass);
297 if (Len(imclass_interfaces) > 0)
298 Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
299 Printf(f_im, "{\n");
300
301 // Add the intermediary class methods
302 Replaceall(imclass_class_code, "$module", module_class_name);
303 Replaceall(imclass_class_code, "$dllimport", dllimport);
304 Printv(f_im, imclass_class_code, NIL);
305 Printv(f_im, imclass_cppcasts_code, NIL);
306
307 // Finish off the class
308 Printf(f_im, "}\n");
309 Printf(f_im, Len(namespce) > 0 ? "\n}\n" : "");
310 Close(f_im);
311 }
312
313 // Generate the C# module class
314 {
315 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name);
316 File *f_module = NewFile(filen,"w");
317 if(!f_module) {
318 Printf(stderr,"Unable to open %s\n", filen);
319 SWIG_exit(EXIT_FAILURE);
320 }
321 Delete(filen); filen = NULL;
322
323 // Start writing out the module class file
324 emitBanner(f_module);
325
326 if(Len(namespce) > 0)
327 Printf(f_module, "namespace %s {\n", namespce);
328
329 if(module_imports)
330 Printf(f_module, "%s\n", module_imports);
331
332 if (Len(module_class_modifiers) > 0)
333 Printf(f_module, "%s ", module_class_modifiers);
334 Printf(f_module, "%s ", module_class_name);
335
336 if (module_baseclass && *Char(module_baseclass))
337 Printf(f_module, ": %s ", module_baseclass);
338 if (Len(module_interfaces) > 0)
339 Printv(f_module, "implements ", module_interfaces, " ", NIL);
340 Printf(f_module, "{\n");
341
342 Replaceall(module_class_code, "$module", module_class_name);
343 Replaceall(module_class_constants_code, "$module", module_class_name);
344
345 Replaceall(module_class_code, "$dllimport", dllimport);
346 Replaceall(module_class_constants_code, "$dllimport", dllimport);
347
348 // Add the wrapper methods
349 Printv(f_module, module_class_code, NIL);
350
351 // Write out all the global constants
352 Printv(f_module, module_class_constants_code, NIL);
353
354 // Finish off the class
355 Printf(f_module, "}\n");
356 Printf(f_module, Len(namespce) > 0 ? "\n}\n" : "");
357
358 Close(f_module);
359 }
360
361 if(upcasts_code)
362 Printv(f_wrappers,upcasts_code,NIL);
363
364 Printf(f_wrappers,"#ifdef __cplusplus\n");
365 Printf(f_wrappers,"}\n");
366 Printf(f_wrappers,"#endif\n");
367
368 // Output a C# type wrapper class for each SWIG type
369 for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
370 emitTypeWrapperClass(swig_type.key, swig_type.item);
371 }
372
373 Delete(swig_types_hash); swig_types_hash = NULL;
374 Delete(imclass_name); imclass_name = NULL;
375 Delete(imclass_class_code); imclass_class_code = NULL;
376 Delete(proxy_class_def); proxy_class_def = NULL;
377 Delete(proxy_class_code); proxy_class_code = NULL;
378 Delete(module_class_constants_code); module_class_constants_code = NULL;
379 Delete(imclass_baseclass); imclass_baseclass = NULL;
380 Delete(imclass_interfaces); imclass_interfaces = NULL;
381 Delete(imclass_class_modifiers); imclass_class_modifiers = NULL;
382 Delete(module_class_name); module_class_name = NULL;
383 Delete(module_class_code); module_class_code = NULL;
384 Delete(module_baseclass); module_baseclass = NULL;
385 Delete(module_interfaces); module_interfaces = NULL;
386 Delete(module_imports); module_imports = NULL;
387 Delete(module_class_modifiers); module_class_modifiers = NULL;
388 Delete(imclass_imports); imclass_imports = NULL;
389 Delete(imclass_cppcasts_code); imclass_cppcasts_code = NULL;
390 Delete(upcasts_code); upcasts_code = NULL;
391 Delete(namespce); namespce = NULL;
392
393 /* Close all of the files */
394 Dump(f_header,f_runtime);
395 Dump(f_wrappers,f_runtime);
396 Wrapper_pretty_print(f_init,f_runtime);
397 Delete(f_header);
398 Delete(f_wrappers);
399 Delete(f_init);
400 Close(f_runtime);
401 Delete(f_runtime);
402 return SWIG_OK;
403 }
404
405 /* -----------------------------------------------------------------------------
406 * emitBanner()
407 * ----------------------------------------------------------------------------- */
408
409 void emitBanner(File *f) {
410 Printf(f, "/* ----------------------------------------------------------------------------\n");
411 Printf(f, " * This file was automatically generated by SWIG (http://www.swig.org).\n");
412 Printf(f, " * Version %s\n", PACKAGE_VERSION);
413 Printf(f, " *\n");
414 Printf(f, " * Do not make changes to this file unless you know what you are doing--modify\n");
415 Printf(f, " * the SWIG interface file instead.\n");
416 Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
417 }
418
419 /* ----------------------------------------------------------------------
420 * nativeWrapper()
421 * ---------------------------------------------------------------------- */
422
423 virtual int nativeWrapper(Node *n) {
424 String *wrapname = Getattr(n,"wrap:name");
425
426 if (!addSymbol(wrapname,n)) return SWIG_ERROR;
427
428 if (Getattr(n,"type")) {
429 Swig_save("nativeWrapper",n,"name",NIL);
430 Setattr(n,"name", wrapname);
431 native_function_flag = true;
432 functionWrapper(n);
433 Swig_restore(n);
434 native_function_flag = false;
435 } else {
436 Printf(stderr,"%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n,"wrap:name"));
437 }
438
439 return SWIG_OK;
440 }
441
442 /* ----------------------------------------------------------------------
443 * functionWrapper()
444 * ---------------------------------------------------------------------- */
445
446 virtual int functionWrapper(Node *n) {
447 String *symname = Getattr(n,"sym:name");
448 SwigType *t = Getattr(n,"type");
449 ParmList *l = Getattr(n,"parms");
450 String *tm;
451 Parm *p;
452 int i;
453 String *c_return_type = NewString("");
454 String *im_return_type = NewString("");
455 String *cleanup = NewString("");
456 String *outarg = NewString("");
457 String *body = NewString("");
458 int num_arguments = 0;
459 int num_required = 0;
460 bool is_void_return;
461 String *overloaded_name = getOverloadedName(n);
462
463 if (!Getattr(n,"sym:overloaded")) {
464 if (!addSymbol(Getattr(n,"sym:name"),n)) return SWIG_ERROR;
465 }
466
467 /*
468 * Generate the proxy class properties for public member variables.
469 * Not for enums and constants.
470 */
471 if(proxy_flag && wrapping_member_flag && !enum_constant_flag) {
472 // Capitalize the first letter in the variable in the getter/setter function name
473 bool getter_flag = Cmp(symname, Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) != 0;
474
475 String *getter_setter_name = NewString("");
476 if(!getter_flag)
477 Printf(getter_setter_name,"set");
478 else
479 Printf(getter_setter_name,"get");
480 Putc(toupper((int) *Char(variable_name)), getter_setter_name);
481 Printf(getter_setter_name, "%s", Char(variable_name)+1);
482
483 Setattr(n,"proxyfuncname", getter_setter_name);
484 Setattr(n,"imfuncname", symname);
485
486 proxyClassFunctionHandler(n);
487 Delete(getter_setter_name);
488 }
489
490 /*
491 The rest of this function deals with generating the intermediary class wrapper function (that wraps
492 a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
493 matching PInvoke c function call.
494 */
495
496 // A new wrapper function object
497 Wrapper *f = NewWrapper();
498
499 // Make a wrapper name for this function
500 String *wname = Swig_name_wrapper(overloaded_name);
501
502 /* Attach the non-standard typemaps to the parameter list. */
503 Swig_typemap_attach_parms("ctype", l, f);
504 Swig_typemap_attach_parms("imtype", l, f);
505
506 /* Get return types */
507 if ((tm = Swig_typemap_lookup_new("ctype",n,"",0))) {
508 Printf(c_return_type,"%s", tm);
509 } else {
510 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
511 "No ctype typemap defined for %s\n", SwigType_str(t,0));
512 }
513
514 if ((tm = Swig_typemap_lookup_new("imtype",n,"",0))) {
515 Printf(im_return_type,"%s", tm);
516 } else {
517 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number,
518 "No imtype typemap defined for %s\n", SwigType_str(t,0));
519 }
520
521 is_void_return = (Cmp(c_return_type, "void") == 0);
522 if (!is_void_return)
523 Wrapper_add_localv(f,"jresult", c_return_type, "jresult = 0",NIL);
524
525 Printv(f->def, " DllExport ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
526
527 // Emit all of the local variables for holding arguments.
528 emit_args(t,l,f);
529
530 /* Attach the standard typemaps */
531 emit_attach_parmmaps(l,f);
532
533 // Parameter overloading
534 Setattr(n,"wrap:parms",l);
535 Setattr(n,"wrap:name", wname);
536
537 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
538 if (Getattr(n,"sym:overloaded")) {
539 // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
540 Swig_overload_check(n);
541 if (Getattr(n, "overload:ignore"))
542 return SWIG_OK;
543 }
544
545 Printv(imclass_class_code,
546 "\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", overloaded_name, "\")]\n", NIL);
547
548 Printf(imclass_class_code, " public static extern %s %s(", im_return_type, overloaded_name);
549
550
551 /* Get number of required and total arguments */
552 num_arguments = emit_num_arguments(l);
553 num_required = emit_num_required(l);
554 int gencomma = 0;
555
556 // Now walk the function parameter list and generate code to get arguments
557 for (i = 0, p=l; i < num_arguments; i++) {
558
559 while (checkAttribute(p,"tmap:in:numinputs","0")) {
560 p = Getattr(p,"tmap:in:next");
561 }
562
563 SwigType *pt = Getattr(p,"type");
564 String *ln = Getattr(p,"lname");
565 String *im_param_type = NewString("");
566 String *c_param_type = NewString("");
567 String *arg = NewString("");
568
569 Printf(arg,"j%s", ln);
570
571 /* Get the ctype types of the parameter */
572 if ((tm = Getattr(p,"tmap:ctype"))) {
573 Printv(c_param_type, tm, NIL);
574 } else {
575 Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
576 "No ctype typemap defined for %s\n", SwigType_str(pt,0));
577 }
578
579 /* Get the intermediary class parameter types of the parameter */
580 if ((tm = Getattr(p,"tmap:imtype"))) {
581 Printv(im_param_type, tm, NIL);
582 } else {
583 Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number,
584 "No imtype typemap defined for %s\n", SwigType_str(pt,0));
585 }
586
587 /* Add parameter to intermediary class method */
588 if(gencomma) Printf(imclass_class_code, ", ");
589 Printf(imclass_class_code, "%s %s", im_param_type, arg);
590
591 // Add parameter to C function
592 Printv(f->def, gencomma?", ":"", c_param_type, " ", arg, NIL);
593
594 gencomma = 1;
595
596 // Get typemap for this argument
597 if ((tm = Getattr(p,"tmap:in"))) {
598 addThrows(n, "tmap:in", p);
599 Replaceall(tm,"$source",arg); /* deprecated */
600 Replaceall(tm,"$target",ln); /* deprecated */
601 Replaceall(tm,"$arg",arg); /* deprecated? */
602 Replaceall(tm,"$input", arg);
603 Setattr(p,"emit:input", arg);
604 Printf(f->code,"%s\n", tm);
605 p = Getattr(p,"tmap:in:next");
606 } else {
607 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number,
608 "Unable to use type %s as a function argument.\n",SwigType_str(pt,0));
609 p = nextSibling(p);
610 }
611 Delete(im_param_type);
612 Delete(c_param_type);
613 Delete(arg);
614 }
615
616 /* Insert constraint checking code */
617 for (p = l; p;) {
618 if ((tm = Getattr(p,"tmap:check"))) {
619 addThrows(n, "tmap:check", p);
620 Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */
621 Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */
622 Replaceall(tm,"$input",Getattr(p,"emit:input"));
623 Printv(f->code,tm,"\n",NIL);
624 p = Getattr(p,"tmap:check:next");
625 } else {
626 p = nextSibling(p);
627 }
628 }
629
630 /* Insert cleanup code */
631 for (p = l; p;) {
632 if ((tm = Getattr(p,"tmap:freearg"))) {
633 addThrows(n, "tmap:freearg", p);
634 Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */
635 Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */
636 Replaceall(tm,"$input",Getattr(p,"emit:input"));
637 Printv(cleanup,tm,"\n",NIL);
638 p = Getattr(p,"tmap:freearg:next");
639 } else {
640 p = nextSibling(p);
641 }
642 }
643
644 /* Insert argument output code */
645 for (p = l; p;) {
646 if ((tm = Getattr(p,"tmap:argout"))) {
647 addThrows(n, "tmap:argout", p);
648 Replaceall(tm,"$source",Getattr(p,"emit:input")); /* deprecated */
649 Replaceall(tm,"$target",Getattr(p,"lname")); /* deprecated */
650 Replaceall(tm,"$arg",Getattr(p,"emit:input")); /* deprecated? */
651 Replaceall(tm,"$result","jresult");
652 Replaceall(tm,"$input",Getattr(p,"emit:input"));
653 Printv(outarg,tm,"\n",NIL);
654 p = Getattr(p,"tmap:argout:next");
655 } else {
656 p = nextSibling(p);
657 }
658 }
659
660 // Get any C# exception classes in the throws typemap
661 ParmList *throw_parm_list = NULL;
662 if ((throw_parm_list = Getattr(n,"throws"))) {
663 Swig_typemap_attach_parms("throws", throw_parm_list, f);
664 for (p = throw_parm_list; p; p=nextSibling(p)) {
665 if ((tm = Getattr(p,"tmap:throws"))) {
666 addThrows(n, "tmap:throws", p);
667 }
668 }
669 }
670
671 if (Cmp(nodeType(n), "constant") == 0) {
672 // Wrapping a constant hack
673 Swig_save("functionWrapper",n,"wrap:action",NIL);
674
675 // below based on Swig_VargetToFunction()
676 SwigType *ty = Swig_wrapped_var_type(Getattr(n,"type"));
677 Setattr(n,"wrap:action", NewStringf("result = (%s) %s;\n", SwigType_lstr(ty,0), Getattr(n, "value")));
678 }
679
680 // Now write code to make the function call
681 if(!native_function_flag)
682 emit_action(n,f);
683
684 if (Cmp(nodeType(n), "constant") == 0)
685 Swig_restore(n);
686
687 /* Return value if necessary */
688 if(!native_function_flag) {
689 if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) {
690 addThrows(n, "tmap:out", n);
691 Replaceall(tm,"$source", "result"); /* deprecated */
692 Replaceall(tm,"$target", "jresult"); /* deprecated */
693 Replaceall(tm,"$result","jresult");
694 Printf(f->code,"%s", tm);
695 if (Len(tm))
696 Printf(f->code,"\n");
697 } else {
698 Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
699 "Unable to use return type %s in function %s.\n", SwigType_str(t,0), Getattr(n,"name"));
700 }
701 }
702
703 /* Output argument output code */
704 Printv(f->code,outarg,NIL);
705
706 /* Output cleanup code */
707 Printv(f->code,cleanup,NIL);
708
709 /* Look to see if there is any newfree cleanup code */
710 if (Getattr(n,"feature:new")) {
711 if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) {
712 addThrows(n, "tmap:newfree", n);
713 Replaceall(tm,"$source","result"); /* deprecated */
714 Printf(f->code,"%s\n",tm);
715 }
716 }
717
718 /* See if there is any return cleanup code */
719 if(!native_function_flag) {
720 if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) {
721 Replaceall(tm,"$source","result"); /* deprecated */
722 Printf(f->code,"%s\n",tm);
723 }
724 }
725
726 /* Finish C function and intermediary class function definitions */
727 Printf(imclass_class_code, ")");
728 generateThrowsClause(n, imclass_class_code);
729 Printf(imclass_class_code, ";\n");
730
731 Printf(f->def,") {");
732
733 if(!is_void_return)
734 Printv(f->code, " return jresult;\n", NIL);
735 Printf(f->code, "}\n");
736
737 /* Substitute the cleanup code */
738 Replaceall(f->code,"$cleanup",cleanup);
739
740 /* Contract macro modification */
741 Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
742
743 if(!is_void_return)
744 Replaceall(f->code,"$null","0");
745 else
746 Replaceall(f->code,"$null","");
747
748 /* Dump the function out */
749 if(!native_function_flag)
750 Wrapper_print(f,f_wrappers);
751
752 if(!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
753 moduleClassFunctionHandler(n);
754 }
755
756 Delete(c_return_type);
757 Delete(im_return_type);
758 Delete(cleanup);
759 Delete(outarg);
760 Delete(body);
761 Delete(overloaded_name);
762 DelWrapper(f);
763 return SWIG_OK;
764 }
765
766 /* -----------------------------------------------------------------------
767 * variableWrapper()
768 * ----------------------------------------------------------------------- */
769
770 virtual int variableWrapper(Node *n) {
771 Language::variableWrapper(n);
772 return SWIG_OK;
773 }
774
775 /* -----------------------------------------------------------------------
776 * globalvariableHandler()
777 * ------------------------------------------------------------------------ */
778
779 virtual int globalvariableHandler(Node *n) {
780
781 SwigType *t = Getattr(n,"type");
782 String *tm;
783
784 // Get the variable type
785 if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
786 substituteClassname(t, tm);
787 } else {
788 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
789 "No cstype typemap defined for %s\n", SwigType_str(t,0));
790 }
791
792 // Output the property's field declaration and accessor methods
793 Printf(module_class_code, " public static %s %s {", tm, Getattr(n, "sym:name"));
794
795 variable_name = Getattr(n,"sym:name");
796 global_variable_flag = true;
797 int ret = Language::globalvariableHandler(n);
798 global_variable_flag = false;
799
800 Printf(module_class_code, "\n }\n\n");
801
802 return ret;
803 }
804
805 /* ----------------------------------------------------------------------
806 * enumDeclaration()
807 *
808 * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
809 * 1) Simple enums - simple constant within the proxy class or module class
810 * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
811 * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
812 * 4) Proper enums - proper C# enum
813 * Anonymous enums always default to 1)
814 * ---------------------------------------------------------------------- */
815
816 virtual int enumDeclaration(Node *n) {
817
818 if (!ImportMode) {
819 if (getCurrentClass() && (cplus_mode != PUBLIC)) return SWIG_NOWRAP;
820
821 enum_code = NewString("");
822 String *symname = Getattr(n,"sym:name");
823 String *constants_code = (proxy_flag && is_wrapping_class()) ? proxy_class_constants_code : module_class_constants_code;
824 EnumFeature enum_feature = decodeEnumFeature(n);
825 String *typemap_lookup_type = Getattr(n,"name");
826
827 if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
828 // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
829
830 // Pure C# baseclass and interfaces
831 const String *pure_baseclass = typemapLookup("csbase", typemap_lookup_type, WARN_NONE);
832 const String *pure_interfaces = typemapLookup("csinterfaces", typemap_lookup_type, WARN_NONE);
833
834 // Emit the enum
835 Printv(enum_code,
836 typemapLookup("csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
837 " ",
838 symname,
839 (*Char(pure_baseclass) || *Char(pure_interfaces)) ?
840 " : " :
841 "",
842 pure_baseclass,
843 ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
844 ", " :
845 "",
846 pure_interfaces,
847 " {\n",
848 NIL);
849 } else {
850 // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
851 if (symname && !Getattr(n,"unnamedinstance"))
852 Printf(constants_code, " // %s \n", symname);
853 }
854
855 // Emit each enum item
856 Language::enumDeclaration(n);
857
858 if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
859 // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
860 // Finish the enum declaration
861 // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
862 Printv(enum_code,
863 (enum_feature == ProperEnum) ?
864 "\n" :
865 typemapLookup("csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
866 typemapLookup("cscode", typemap_lookup_type, WARN_NONE), // extra C# code
867 "}\n",
868 "\n",
869 NIL);
870
871 Replaceall(enum_code, "$csclassname", symname);
872
873 // Substitute $enumvalues - intended usage is for typesafe enums
874 if (Getattr(n,"enumvalues"))
875 Replaceall(enum_code, "$enumvalues", Getattr(n,"enumvalues"));
876 else
877 Replaceall(enum_code, "$enumvalues", "");
878
879 if (proxy_flag && is_wrapping_class()) {
880 // Enums defined within the C++ class are defined within the proxy class
881
882 // Add extra indentation
883 Replaceall(enum_code, "\n ", "\n ");
884 Replaceall(enum_code, "\n}\n", "\n }\n");
885
886 Printv(proxy_class_constants_code, " ", enum_code, NIL);
887 } else {
888 // Global enums are defined in their own file
889 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), symname);
890 File *f_enum = NewFile(filen,"w");
891 if(!f_enum) {
892 Printf(stderr,"Unable to open %s\n", filen);
893 SWIG_exit(EXIT_FAILURE);
894 }
895 Delete(filen); filen = NULL;
896
897 // Start writing out the enum file
898 emitBanner(f_enum);
899
900 if(Len(namespce) > 0)
901 Printf(f_enum, "namespace %s {\n", namespce);
902
903 Printv(f_enum,
904 typemapLookup("csimports", typemap_lookup_type, WARN_NONE), // Import statements
905 "\n",
906 enum_code,
907 NIL);
908
909 Printf(f_enum, Len(namespce) > 0 ? "\n}\n" : "\n");
910 Close(f_enum);
911 }
912 } else {
913 // Wrap C++ enum with simple constant
914 Printf(enum_code, "\n");
915 if (proxy_flag && is_wrapping_class())
916 Printv(proxy_class_constants_code, enum_code, NIL);
917 else
918 Printv(module_class_constants_code, enum_code, NIL);
919 }
920
921 Delete(enum_code); enum_code = NULL;
922 }
923 return SWIG_OK;
924 }
925
926 /* ----------------------------------------------------------------------
927 * enumvalueDeclaration()
928 * ---------------------------------------------------------------------- */
929
930 virtual int enumvalueDeclaration(Node *n) {
931 if (getCurrentClass() && (cplus_mode != PUBLIC)) return SWIG_NOWRAP;
932
933 Swig_require("enumvalueDeclaration",n,"*name", "?value",NIL);
934 String *symname = Getattr(n,"sym:name");
935 String *value = Getattr(n,"value");
936 String *name = Getattr(n,"name");
937 String *tmpValue;
938
939 // Strange hack from parent method
940 if (value)
941 tmpValue = NewString(value);
942 else
943 tmpValue = NewString(name);
944 // Note that this is used in enumValue() amongst other places
945 Setattr(n, "value", tmpValue);
946
947 {
948 EnumFeature enum_feature = decodeEnumFeature(parentNode(n));
949
950 if ((enum_feature == ProperEnum) && Getattr(parentNode(n),"sym:name") && !Getattr(parentNode(n),"unnamedinstance")) {
951 // Wrap (non-anonymous) C/C++ enum with a proper C# enum
952 // Emit the enum item.
953 if (!Getattr(n,"_last")) // Only the first enum item has this attribute set
954 Printf(enum_code, ",\n");
955 Printf(enum_code, " %s", symname);
956
957 // Check for the %csconstvalue feature
958 String *value = Getattr(n,"feature:cs:constvalue");
959
960 // Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
961 value = value ? value : Getattr(n,"enumvalue");
962 if (value) {
963 Printf(enum_code, " = %s", value);
964 }
965 } else {
966 // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
967 const String *parent_name = Getattr(parentNode(n),"name");
968 String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int");
969 const String *tm = typemapLookup("cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF);
970 String *return_type = Copy(tm);
971 Delete(typemap_lookup_type); typemap_lookup_type = NULL;
972
973 // The %csconst feature determines how the constant value is obtained
974 String *const_feature = Getattr(n,"feature:cs:const");
975 bool const_feature_flag = const_feature && Cmp(const_feature, "0") != 0;
976
977 if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n),"sym:name") && !Getattr(parentNode(n),"unnamedinstance")) {
978 // Wrap (non-anonymouse) enum using the typesafe enum pattern
979 if (Getattr(n,"enumvalue")) {
980 String *value = enumValue(n);
981 Printf(enum_code, " public static readonly %s %s = new %s(\"%s\", %s);\n", return_type, symname, return_type, symname, value);
982 Delete(value);
983 } else {
984 Printf(enum_code, " public static readonly %s %s = new %s(\"%s\");\n", return_type, symname, return_type, symname);
985 }
986 } else {
987 // Simple integer constants
988 // Note these are always generated for anonymous enums, no matter what enum_feature is specified
989 // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
990 const char *const_readonly = const_feature_flag ? "const" : "static readonly";
991 String *value = enumValue(n);
992 Printf(enum_code, " public %s %s %s = %s;\n", const_readonly, return_type, symname, value);
993 Delete(value);
994 }
995 }
996
997 // Add the enum value to the comma separated list being constructed in the enum declaration.
998 String *enumvalues = Getattr(parentNode(n), "enumvalues");
999 if (!enumvalues)
1000 Setattr(parentNode(n), "enumvalues", Copy(symname));
1001 else
1002 Printv(enumvalues, ", ", symname, NIL);
1003 }
1004
1005 Delete(tmpValue);
1006 Swig_restore(n);
1007 return SWIG_OK;
1008 }
1009
1010 /* -----------------------------------------------------------------------
1011 * constantWrapper()
1012 * Used for wrapping constants - #define or %constant.
1013 * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
1014 * C# static const variables are generated for these.
1015 * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
1016 * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
1017 * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
1018 * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
1019 * ------------------------------------------------------------------------ */
1020
1021 virtual int constantWrapper(Node *n) {
1022 String *symname = Getattr(n,"sym:name");
1023 SwigType *t = Getattr(n,"type");
1024 ParmList *l = Getattr(n,"parms");
1025 String *tm;
1026 String *return_type = NewString("");
1027 String *constants_code = NewString("");
1028
1029 if (!addSymbol(symname,n)) return SWIG_ERROR;
1030
1031 bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
1032
1033 // The %csconst feature determines how the constant value is obtained
1034 String *const_feature = Getattr(n,"feature:cs:const");
1035 bool const_feature_flag = const_feature && Cmp(const_feature, "0") != 0;
1036
1037 /* Adjust the enum type for the Swig_typemap_lookup.
1038 * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
1039 if (is_enum_item) {
1040 t = Getattr(parentNode(n),"enumtype");
1041 Setattr(n,"type", t);
1042 }
1043
1044 /* Attach the non-standard typemaps to the parameter list. */
1045 Swig_typemap_attach_parms("cstype", l, NULL);
1046
1047 /* Get C# return types */
1048 bool classname_substituted_flag = false;
1049
1050 if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
1051 classname_substituted_flag = substituteClassname(t, tm);
1052 Printf(return_type, "%s", tm);
1053 } else {
1054 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
1055 "No cstype typemap defined for %s\n", SwigType_str(t,0));
1056 }
1057
1058 // Add the stripped quotes back in
1059 String *new_value = NewString("");
1060 Swig_save("constantWrapper",n,"value",NIL);
1061 if(SwigType_type(t) == T_STRING) {
1062 Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
1063 Setattr(n, "value", new_value);
1064 }
1065 else if(SwigType_type(t) == T_CHAR) {
1066 Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
1067 Setattr(n, "value", new_value);
1068 }
1069
1070 const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
1071 Printf(constants_code, " public %s %s %s = ", (const_feature_flag ? "const" : "static readonly"), return_type, itemname);
1072
1073 // Check for the %csconstvalue feature
1074 String *value = Getattr(n,"feature:cs:constvalue");
1075
1076 if (value) {
1077 Printf(constants_code, "%s;\n", value);
1078 } else if (!const_feature_flag) {
1079 // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call.
1080
1081 if(classname_substituted_flag) {
1082 if (SwigType_isenum(t)) {
1083 // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
1084 Printf(constants_code, "(%s)%s.%s();\n", return_type, imclass_name, Swig_name_get(symname));
1085 } else {
1086 // This handles function pointers using the %constant directive
1087 Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
1088 }
1089 } else
1090 Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname));
1091
1092 // Each constant and enum value is wrapped with a separate PInvoke function call
1093 enum_constant_flag = true;
1094 variableWrapper(n);
1095 enum_constant_flag = false;
1096 } else {
1097 // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
1098 Printf(constants_code, "%s;\n", Getattr(n,"value"));
1099 }
1100
1101 // Emit the generated code to appropriate place
1102 // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed
1103 if (!is_enum_item) {
1104 if(proxy_flag && wrapping_member_flag)
1105 Printv(proxy_class_constants_code, constants_code, NIL);
1106 else
1107 Printv(module_class_constants_code, constants_code, NIL);
1108 }
1109
1110 // Cleanup
1111 Swig_restore(n);
1112 Delete(new_value);
1113 Delete(return_type);
1114 Delete(constants_code);
1115 return SWIG_OK;
1116 }
1117
1118 /* -----------------------------------------------------------------------------
1119 * insertDirective()
1120 * ----------------------------------------------------------------------------- */
1121
1122 virtual int insertDirective(Node *n) {
1123 String *code = Getattr(n,"code");
1124 Replaceall(code, "$module", module_class_name);
1125 Replaceall(code, "$dllimport", dllimport);
1126 return Language::insertDirective(n);
1127 }
1128
1129 /* -----------------------------------------------------------------------------
1130 * pragmaDirective()
1131 *
1132 * Valid Pragmas:
1133 * imclassbase - base (extends) for the intermediary class
1134 * imclassclassmodifiers - class modifiers for the intermediary class
1135 * imclasscode - text (C# code) is copied verbatim to the intermediary class
1136 * imclassimports - import statements for the intermediary class
1137 * imclassinterfaces - interface (implements) for the intermediary class
1138 *
1139 * modulebase - base (extends) for the module class
1140 * moduleclassmodifiers - class modifiers for the module class
1141 * modulecode - text (C# code) is copied verbatim to the module class
1142 * moduleimports - import statements for the module class
1143 * moduleinterfaces - interface (implements) for the module class
1144 *
1145 * ----------------------------------------------------------------------------- */
1146
1147 virtual int pragmaDirective(Node *n) {
1148 if (!ImportMode) {
1149 String *lang = Getattr(n,"lang");
1150 String *code = Getattr(n,"name");
1151 String *value = Getattr(n,"value");
1152
1153 if(Strcmp(lang, "csharp") == 0) {
1154
1155 String *strvalue = NewString(value);
1156 Replaceall(strvalue,"\\\"", "\"");
1157
1158 if(Strcmp(code, "imclassbase") == 0) {
1159 Delete(imclass_baseclass);
1160 imclass_baseclass = Copy(strvalue);
1161 }
1162 else if(Strcmp(code, "imclassclassmodifiers") == 0) {
1163 Delete(imclass_class_modifiers);
1164 imclass_class_modifiers = Copy(strvalue);
1165 }
1166 else if(Strcmp(code, "imclasscode") == 0) {
1167 Printf(imclass_class_code, "%s\n", strvalue);
1168 }
1169 else if(Strcmp(code, "imclassimports") == 0) {
1170 Delete(imclass_imports);
1171 imclass_imports = Copy(strvalue);
1172 }
1173 else if(Strcmp(code, "imclassinterfaces") == 0) {
1174 Delete(imclass_interfaces);
1175 imclass_interfaces = Copy(strvalue);
1176 }
1177 else if(Strcmp(code, "modulebase") == 0) {
1178 Delete(module_baseclass);
1179 module_baseclass = Copy(strvalue);
1180 }
1181 else if(Strcmp(code, "moduleclassmodifiers") == 0) {
1182 Delete(module_class_modifiers);
1183 module_class_modifiers = Copy(strvalue);
1184 }
1185 else if(Strcmp(code, "modulecode") == 0) {
1186 Printf(module_class_code, "%s\n", strvalue);
1187 }
1188 else if(Strcmp(code, "moduleimports") == 0) {
1189 Delete(module_imports);
1190 module_imports = Copy(strvalue);
1191 }
1192 else if(Strcmp(code, "moduleinterfaces") == 0) {
1193 Delete(module_interfaces);
1194 module_interfaces = Copy(strvalue);
1195 } else {
1196 Printf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
1197 }
1198 Delete(strvalue);
1199 }
1200 }
1201 return Language::pragmaDirective(n);
1202 }
1203
1204 /* -----------------------------------------------------------------------------
1205 * emitProxyClassDefAndCPPCasts()
1206 * ----------------------------------------------------------------------------- */
1207
1208 void emitProxyClassDefAndCPPCasts(Node *n) {
1209 String *c_classname = SwigType_namestr(Getattr(n,"name"));
1210 String *c_baseclass = NULL;
1211 String *baseclass = NULL;
1212 String *c_baseclassname = NULL;
1213 String *typemap_lookup_type = Getattr(n,"classtypeobj");
1214
1215 /* Deal with inheritance */
1216 List *baselist = Getattr(n,"bases");
1217 if (baselist) {
1218 Iterator base = First(baselist);
1219 c_baseclassname = Getattr(base.item,"name");
1220 baseclass = Copy(getProxyName(c_baseclassname));
1221 if (baseclass){
1222 c_baseclass = SwigType_namestr(Getattr(base.item,"name"));
1223 }
1224 base = Next(base);
1225 if (base.item) {
1226 Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
1227 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", typemap_lookup_type, Getattr(base.item,"name"));
1228 }
1229 }
1230
1231 bool derived = baseclass && getProxyName(c_baseclassname);
1232 if (!baseclass)
1233 baseclass = NewString("");
1234
1235 // Inheritance from pure C# classes
1236 const String *pure_baseclass = typemapLookup("csbase", typemap_lookup_type, WARN_NONE);
1237 if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
1238 Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
1239 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", typemap_lookup_type, pure_baseclass);
1240 pure_baseclass = empty_string;
1241 }
1242
1243 // Pure C# interfaces
1244 const String *pure_interfaces = typemapLookup(derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
1245
1246 // Start writing the proxy class
1247 Printv(proxy_class_def,
1248 typemapLookup("csimports", typemap_lookup_type, WARN_NONE), // Import statements
1249 "\n",
1250 typemapLookup("csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
1251 " $csclassname", // Class name and base class
1252 (derived || *Char(pure_baseclass) || *Char(pure_interfaces)) ?
1253 " : " :
1254 "",
1255 baseclass, // Note only one of these base classes should ever be set as multiple inheritance is not permissible
1256 pure_baseclass,
1257 ((derived || *Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
1258 ", " :
1259 "",
1260 pure_interfaces,
1261 " {",
1262 derived ?
1263 typemapLookup("csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
1264 typemapLookup("csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
1265 NIL);
1266
1267 if(!have_default_constructor_flag) { // All proxy classes need a constructor
1268 Printv(proxy_class_def,
1269 "\n",
1270 " protected $csclassname() : this(IntPtr.Zero, false) {\n",
1271 " }\n",
1272 NIL);
1273 }
1274
1275 // C++ destructor is wrapped by the Dispose method
1276 // Note that the method name is specified in a typemap attribute called methodname
1277 String *destruct = NewString("");
1278 const String *tm = NULL;
1279 Node *attributes = NewHash();
1280 String *destruct_methodname = NULL;
1281 if (derived) {
1282 tm = typemapLookup("csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
1283 destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname");
1284 } else {
1285 tm = typemapLookup("csdestruct", typemap_lookup_type, WARN_NONE, attributes);
1286 destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname");
1287 }
1288 if (!destruct_methodname) {
1289 Swig_error(input_file, line_number,
1290 "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
1291 }
1292
1293 // Emit the Finalize and Dispose methods
1294 if (tm) {
1295 // Finalize method
1296 if (*Char(destructor_call)) {
1297 Printv(proxy_class_def,
1298 typemapLookup("csfinalize", typemap_lookup_type, WARN_NONE),
1299 NIL);
1300 }
1301 // Dispose method
1302 Printv(destruct, tm, NIL);
1303 if (*Char(destructor_call))
1304 Replaceall(destruct, "$imcall", destructor_call);
1305 else
1306 Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
1307 if (*Char(destruct))
1308 Printv(proxy_class_def, "\n public ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n", NIL);
1309 }
1310 Delete(attributes);
1311 Delete(destruct);
1312
1313 // Emit extra user code
1314 Printv(proxy_class_def,
1315 typemapLookup("cscode", typemap_lookup_type, WARN_NONE), // extra C# code
1316 "\n",
1317 NIL);
1318
1319 // Substitute various strings into the above template
1320 Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
1321 Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
1322
1323 Replaceall(proxy_class_def, "$module", module_class_name);
1324 Replaceall(proxy_class_code, "$module", module_class_name);
1325
1326 Replaceall(proxy_class_def, "$dllimport", dllimport);
1327 Replaceall(proxy_class_code, "$dllimport", dllimport);
1328
1329 // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
1330 if(derived){
1331 Printv(imclass_cppcasts_code,"\n [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", proxy_class_name ,"Upcast", "\")]\n", NIL);
1332 Printf(imclass_cppcasts_code," public static extern IntPtr $csclassnameUpcast(IntPtr objectRef);\n");
1333
1334 Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
1335
1336 Printv(upcasts_code,
1337 "DllExport $cbaseclass * SWIGSTDCALL CSharp_$imclazznameUpcast",
1338 "($cclass *objectRef) {\n",
1339 " return ($cbaseclass *)objectRef;\n"
1340 "}\n",
1341 "\n",
1342 NIL);
1343
1344 Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
1345 Replaceall(upcasts_code, "$imclazzname", proxy_class_name);
1346 Replaceall(upcasts_code, "$cclass", c_classname);
1347 }
1348 Delete(baseclass);
1349 }
1350
1351 /* ----------------------------------------------------------------------
1352 * classHandler()
1353 * ---------------------------------------------------------------------- */
1354
1355 virtual int classHandler(Node *n) {
1356
1357 File *f_proxy = NULL;
1358 if (proxy_flag) {
1359 proxy_class_name = NewString(Getattr(n,"sym:name"));
1360
1361 if (!addSymbol(proxy_class_name,n)) return SWIG_ERROR;
1362
1363 if (Cmp(proxy_class_name, imclass_name) == 0) {
1364 Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
1365 SWIG_exit(EXIT_FAILURE);
1366 }
1367
1368 if (Cmp(proxy_class_name, module_class_name) == 0) {
1369 Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
1370 SWIG_exit(EXIT_FAILURE);
1371 }
1372
1373 String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), proxy_class_name);
1374 f_proxy = NewFile(filen,"w");
1375 if(!f_proxy) {
1376 Printf(stderr, "Unable to create proxy class file: %s\n", filen);
1377 SWIG_exit(EXIT_FAILURE);
1378 }
1379 Delete(filen); filen = NULL;
1380
1381 // Start writing out the proxy class file
1382 emitBanner(f_proxy);
1383
1384 if(Len(namespce) > 0)
1385 Printf(f_proxy, "namespace %s {\n", namespce);
1386
1387 Clear(proxy_class_def);
1388 Clear(proxy_class_code);
1389
1390 have_default_constructor_flag = false;
1391 destructor_call = NewString("");
1392 proxy_class_constants_code = NewString("");
1393 }
1394
1395 Language::classHandler(n);
1396
1397 if (proxy_flag) {
1398
1399 emitProxyClassDefAndCPPCasts(n);
1400
1401 Replaceall(proxy_class_def, "$module", module_class_name);
1402 Replaceall(proxy_class_code, "$module", module_class_name);
1403 Replaceall(proxy_class_constants_code, "$module", module_class_name);
1404
1405 Replaceall(proxy_class_def, "$dllimport", dllimport);
1406 Replaceall(proxy_class_code, "$dllimport", dllimport);
1407 Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
1408
1409 Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
1410
1411 // Write out all the constants
1412 if (Len(proxy_class_constants_code) != 0 )
1413 Printv(f_proxy, proxy_class_constants_code, NIL);
1414
1415 Printf(f_proxy, "}\n");
1416 Printf(f_proxy, Len(namespce) > 0 ? "\n}\n" : "");
1417 Close(f_proxy);
1418 f_proxy = NULL;
1419
1420 Delete(proxy_class_name); proxy_class_name = NULL;
1421 Delete(destructor_call); destructor_call = NULL;
1422 Delete(proxy_class_constants_code); proxy_class_constants_code = NULL;
1423 }
1424 return SWIG_OK;
1425 }
1426
1427 /* ----------------------------------------------------------------------
1428 * memberfunctionHandler()
1429 * ---------------------------------------------------------------------- */
1430
1431 virtual int memberfunctionHandler(Node *n) {
1432 Language::memberfunctionHandler(n);
1433
1434 if (proxy_flag) {
1435 String *overloaded_name = getOverloadedName(n);
1436 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1437 Setattr(n,"proxyfuncname", Getattr(n, "sym:name"));
1438 Setattr(n,"imfuncname", intermediary_function_name);
1439 proxyClassFunctionHandler(n);
1440 Delete(overloaded_name);
1441 }
1442 return SWIG_OK;
1443 }
1444
1445 /* ----------------------------------------------------------------------
1446 * staticmemberfunctionHandler()
1447 * ---------------------------------------------------------------------- */
1448
1449 virtual int staticmemberfunctionHandler(Node *n) {
1450
1451 static_flag = true;
1452 Language::staticmemberfunctionHandler(n);
1453
1454 if (proxy_flag) {
1455 String *overloaded_name = getOverloadedName(n);
1456 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1457 Setattr(n,"proxyfuncname", Getattr(n,"sym:name"));
1458 Setattr(n,"imfuncname", intermediary_function_name);
1459 proxyClassFunctionHandler(n);
1460 Delete(overloaded_name);
1461 }
1462 static_flag = false;
1463
1464 return SWIG_OK;
1465 }
1466
1467
1468 /* -----------------------------------------------------------------------------
1469 * proxyClassFunctionHandler()
1470 *
1471 * Function called for creating a C# wrapper function around a c++ function in the
1472 * proxy class. Used for both static and non-static C++ class functions.
1473 * C++ class static functions map to C# static functions.
1474 * Two extra attributes in the Node must be available. These are "proxyfuncname" -
1475 * the name of the C# class proxy function, which in turn will call "imfuncname" -
1476 * the intermediary (PInvoke) function name in the intermediary class.
1477 * ----------------------------------------------------------------------------- */
1478
1479 void proxyClassFunctionHandler(Node *n) {
1480 SwigType *t = Getattr(n,"type");
1481 ParmList *l = Getattr(n,"parms");
1482 String *intermediary_function_name = Getattr(n,"imfuncname");
1483 String *proxy_function_name = Getattr(n,"proxyfuncname");
1484 String *tm;
1485 Parm *p;
1486 int i;
1487 String *imcall = NewString("");
1488 String *return_type = NewString("");
1489 String *function_code = NewString("");
1490 bool setter_flag = false;
1491
1492 if(!proxy_flag) return;
1493
1494 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
1495 if (Getattr(n, "overload:ignore")) return;
1496
1497 if (l) {
1498 if (SwigType_type(Getattr(l,"type")) == T_VOID) {
1499 l = nextSibling(l);
1500 }
1501 }
1502
1503 /* Attach the non-standard typemaps to the parameter list */
1504 Swig_typemap_attach_parms("in", l, NULL);
1505 Swig_typemap_attach_parms("cstype", l, NULL);
1506 Swig_typemap_attach_parms("csin", l, NULL);
1507
1508 /* Get return types */
1509 if ((tm = Swig_typemap_lookup_new("cstype",n,"",0))) {
1510 // 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
1511 SwigType *virtualtype = Getattr(n,"virtual:type");
1512 substituteClassname(virtualtype ? virtualtype : t, tm);
1513 Printf(return_type, "%s", tm);
1514 if (virtualtype)
1515 Swig_warning(WARN_CSHARP_COVARIANT_RET, input_file, line_number,
1516 "Covariant return types not supported in C#. Proxy method will return %s.\n", SwigType_str(virtualtype,0));
1517 } else {
1518 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
1519 "No cstype typemap defined for %s\n", SwigType_str(t,0));
1520 }
1521
1522 if(proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1523 // Properties
1524 setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0);
1525 }
1526
1527 /* Start generating the proxy function */
1528 const String *methodmods = Getattr(n,"feature:cs:methodmodifiers");
1529 methodmods = methodmods ? methodmods : (!is_public(n) ? protected_string : public_string);
1530 Printf(function_code, " %s ", methodmods);
1531 if (static_flag)
1532 Printf(function_code, "static ");
1533 if (Getattr(n,"virtual:derived"))
1534 Printf(function_code, "override ");
1535 else if (checkAttribute(n, "storage", "virtual"))
1536 Printf(function_code, "virtual ");
1537
1538 Printf(function_code, "%s %s(", return_type, proxy_function_name);
1539
1540 Printv(imcall, imclass_name, ".", intermediary_function_name, "(", NIL);
1541 if (!static_flag)
1542 Printf(imcall, "swigCPtr");
1543
1544 emit_mark_varargs(l);
1545
1546 int gencomma = !static_flag;
1547
1548 /* Output each parameter */
1549 for (i = 0, p=l; p; i++) {
1550
1551 /* Ignored varargs */
1552 if (checkAttribute(p,"varargs:ignore","1")) {
1553 p = nextSibling(p);
1554 continue;
1555 }
1556
1557 /* Ignored parameters */
1558 if (checkAttribute(p,"tmap:in:numinputs","0")) {
1559 p = Getattr(p,"tmap:in:next");
1560 continue;
1561 }
1562
1563 /* Ignore the 'this' argument for variable wrappers */
1564 if (!(variable_wrapper_flag && i==0))
1565 {
1566 SwigType *pt = Getattr(p,"type");
1567 String *param_type = NewString("");
1568
1569 /* Get the C# parameter type */
1570 if ((tm = Getattr(p,"tmap:cstype"))) {
1571 substituteClassname(pt, tm);
1572 Printf(param_type, "%s", tm);
1573 } else {
1574 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
1575 "No cstype typemap defined for %s\n", SwigType_str(pt,0));
1576 }
1577
1578 if (gencomma)
1579 Printf(imcall, ", ");
1580
1581 String *arg = variable_wrapper_flag ? NewString("value") : makeParameterName(n, p, i);
1582
1583 // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
1584 if ((tm = Getattr(p,"tmap:csin"))) {
1585 addThrows(n, "tmap:csin", p);
1586 substituteClassname(pt, tm);
1587 Replaceall(tm, "$csinput", arg);
1588 Printv(imcall, tm, NIL);
1589 } else {
1590 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number,
1591 "No csin typemap defined for %s\n", SwigType_str(pt,0));
1592 }
1593
1594 /* Add parameter to proxy function */
1595 if (gencomma >= 2)
1596 Printf(function_code, ", ");
1597 gencomma = 2;
1598 Printf(function_code, "%s %s", param_type, arg);
1599
1600 Delete(arg);
1601 Delete(param_type);
1602 }
1603 p = Getattr(p,"tmap:in:next");
1604 }
1605
1606 Printf(imcall, ")");
1607 Printf(function_code, ")");
1608
1609 // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
1610 if ((tm = Swig_typemap_lookup_new("csout",n,"",0))) {
1611 addThrows(n, "tmap:csout", n);
1612 if (Getattr(n,"feature:new"))
1613 Replaceall(tm,"$owner","true");
1614 else
1615 Replaceall(tm,"$owner","false");
1616 substituteClassname(t, tm);
1617 Replaceall(tm, "$imcall", imcall);
1618 } else {
1619 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
1620 "No csout typemap defined for %s\n", SwigType_str(t,0));
1621 }
1622
1623 generateThrowsClause(n, function_code);
1624 Printf(function_code, " %s\n\n", tm ? (const String *)tm : empty_string);
1625
1626 if(proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1627 // Properties
1628 if(setter_flag) {
1629 // Setter method
1630 if ((tm = Swig_typemap_lookup_new("csvarin",n,"",0))) {
1631 if (Getattr(n,"feature:new"))
1632 Replaceall(tm,"$owner","true");
1633 else
1634 Replaceall(tm,"$owner","false");
1635 substituteClassname(t, tm);
1636 Replaceall(tm, "$imcall", imcall);
1637 Printf(proxy_class_code, "%s", tm);
1638 } else {
1639 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
1640 "No csvarin typemap defined for %s\n", SwigType_str(t,0));
1641 }
1642 } else {
1643 // Getter method
1644 if ((tm = Swig_typemap_lookup_new("csvarout",n,"",0))) {
1645 if (Getattr(n,"feature:new"))
1646 Replaceall(tm,"$owner","true");
1647 else
1648 Replaceall(tm,"$owner","false");
1649 substituteClassname(t, tm);
1650 Replaceall(tm, "$imcall", imcall);
1651 Printf(proxy_class_code, "%s", tm);
1652 } else {
1653 Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number,
1654 "No csvarout typemap defined for %s\n", SwigType_str(t,0));
1655 }
1656 }
1657 } else {
1658 // Normal function call
1659 Printv(proxy_class_code, function_code, NIL);
1660 }
1661
1662 Delete(function_code);
1663 Delete(return_type);
1664 Delete(imcall);
1665 }
1666
1667 /* ----------------------------------------------------------------------
1668 * constructorHandler()
1669 * ---------------------------------------------------------------------- */
1670
1671 virtual int constructorHandler(Node *n) {
1672
1673 ParmList *l = Getattr(n,"parms");
1674 String *tm;
1675 Parm *p;
1676 int i;
1677
1678 Language::constructorHandler(n);
1679
1680 // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
1681 if (Getattr(n, "overload:ignore"))
1682 return SWIG_OK;
1683
1684 if(proxy_flag) {
1685 String *overloaded_name = getOverloadedName(n);
1686 String *imcall = NewString("");
1687
1688 const String *methodmods = Getattr(n,"feature:cs:methodmodifiers");
1689 methodmods = methodmods ? methodmods : (!is_public(n) ? protected_string : public_string);
1690 methodmods = methodmods ? methodmods : public_string;
1691 Printf(proxy_class_code, " %s %s(", methodmods, proxy_class_name);
1692 Printv(imcall, " : this(", imclass_name, ".", Swig_name_construct(overloaded_name), "(", NIL);
1693
1694 /* Attach the non-standard typemaps to the parameter list */
1695 Swig_typemap_attach_parms("in", l, NULL);
1696 Swig_typemap_attach_parms("cstype", l, NULL);
1697 Swig_typemap_attach_parms("csin", l, NULL);
1698
1699 emit_mark_varargs(l);
1700
1701 int gencomma = 0;
1702
1703 /* Output each parameter */
1704 for (i = 0, p=l; p; i++) {
1705
1706 /* Ignored varargs */
1707 if (checkAttribute(p,"varargs:ignore","1")) {
1708 p = nextSibling(p);
1709 continue;
1710 }
1711
1712 /* Ignored parameters */
1713 if (checkAttribute(p,"tmap:in:numinputs","0")) {
1714 p = Getattr(p,"tmap:in:next");
1715 continue;
1716 }
1717
1718 SwigType *pt = Getattr(p,"type");
1719 String *param_type = NewString("");
1720
1721 /* Get the C# parameter type */
1722 if ((tm = Getattr(p,"tmap:cstype"))) {
1723 substituteClassname(pt, tm);
1724 Printf(param_type, "%s", tm);
1725 } else {
1726 Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number,
1727 "No cstype typemap defined for %s\n", SwigType_str(pt,0));
1728 }
1729
1730 if (gencomma)
1731 Printf(imcall, ", ");
1732
1733 String *arg = makeParameterName(n, p, i);
1734
1735 // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
1736 if ((tm = Getattr(p,"tmap:csin"))) {
1737 addThrows(n, "tmap:csin", p);
1738 substituteClassname(pt, tm);
1739 Replaceall(tm, "$csinput", arg);
1740 Printv(imcall, tm, NIL);
1741 } else {
1742 Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number,
1743 "No csin typemap defined for %s\n", SwigType_str(pt,0));
1744 }
1745
1746 /* Add parameter to proxy function */
1747 if(gencomma)
1748 Printf(proxy_class_code, ", ");
1749 Printf(proxy_class_code, "%s %s", param_type, arg);
1750 gencomma = 1;
1751
1752 Delete(arg);
1753 Delete(param_type);
1754 p = Getattr(p,"tmap:in:next");
1755 }
1756
1757 Printf(imcall, "), true)");
1758
1759 Printf(proxy_class_code, ")");
1760 Printf(proxy_class_code,"%s", imcall);
1761 generateThrowsClause(n, proxy_class_code);
1762 Printf(proxy_class_code, " {\n");
1763 Printf(proxy_class_code, " }\n\n");
1764
1765 if(!gencomma) // We must have a default constructor
1766 have_default_constructor_flag = true;
1767
1768 Delete(overloaded_name);
1769 Delete(imcall);
1770 }
1771
1772 return SWIG_OK;
1773 }
1774
1775 /* ----------------------------------------------------------------------
1776 * destructorHandler(