1 /* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
7 * Java language module for SWIG.
8 * ----------------------------------------------------------------------------- */
10 char cvsroot_java_cxx[] = "$Id: java.cxx 11584 2009-08-16 00:04:29Z wsfulton $";
13 #include <limits.h> // for INT_MAX
17 /* Hash type used for upcalls from C/C++ */
18 typedef DOH UpcallData;
20 class JAVA:public Language {
21 static const char *usage;
22 const String *empty_string;
23 const String *public_string;
24 const String *protected_string;
26 Hash *swig_types_hash;
37 bool proxy_flag; // Flag for generating proxy classes
38 bool nopgcpp_flag; // Flag for suppressing the premature garbage collection prevention parameter
39 bool native_function_flag; // Flag for when wrapping a native function
40 bool enum_constant_flag; // Flag for when wrapping an enum or constant
41 bool static_flag; // Flag for when wrapping a static functions or member variables
42 bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
43 bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
44 bool global_variable_flag; // Flag for when wrapping a global variable
45 bool old_variable_names; // Flag for old style variable names in the intermediary class
46 bool member_func_flag; // flag set when wrapping a member function
48 String *imclass_name; // intermediary class name
49 String *module_class_name; // module class name
50 String *imclass_class_code; // intermediary class code
51 String *proxy_class_def;
52 String *proxy_class_code;
53 String *module_class_code;
54 String *proxy_class_name;
55 String *variable_name; //Name of a variable being wrapped
56 String *proxy_class_constants_code;
57 String *module_class_constants_code;
59 String *package; // Optional package name
60 String *jnipackage; // Package name used in the JNI code
61 String *package_path; // Package name used internally by JNI (slashes)
62 String *imclass_imports; //intermediary class imports from %pragma
63 String *module_imports; //module imports from %pragma
64 String *imclass_baseclass; //inheritance for intermediary class class from %pragma
65 String *module_baseclass; //inheritance for module class from %pragma
66 String *imclass_interfaces; //interfaces for intermediary class class from %pragma
67 String *module_interfaces; //interfaces for module class from %pragma
68 String *imclass_class_modifiers; //class modifiers for intermediary class overriden by %pragma
69 String *module_class_modifiers; //class modifiers for module class overriden by %pragma
70 String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
71 String *imclass_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
72 String *imclass_directors; // Intermediate class director code
73 String *destructor_call; //C++ destructor call if any
74 String *destructor_throws_clause; //C++ destructor throws clause if any
76 // Director method stuff:
81 int first_class_dmethod;
82 int curr_class_dmethod;
84 enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
86 static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) {
87 Parm *p = NewParm(type, name);
88 Setfile(p, Getfile(n));
89 Setline(p, Getline(n));
95 /* -----------------------------------------------------------------------------
97 * ----------------------------------------------------------------------------- */
99 JAVA():empty_string(NewString("")),
100 public_string(NewString("public")),
101 protected_string(NewString("protected")),
102 swig_types_hash(NULL),
111 filenames_list(NULL),
114 native_function_flag(false),
115 enum_constant_flag(false),
117 variable_wrapper_flag(false),
118 wrapping_member_flag(false),
119 global_variable_flag(false),
120 old_variable_names(false),
121 member_func_flag(false),
123 module_class_name(NULL),
124 imclass_class_code(NULL),
125 proxy_class_def(NULL),
126 proxy_class_code(NULL),
127 module_class_code(NULL),
128 proxy_class_name(NULL),
130 proxy_class_constants_code(NULL),
131 module_class_constants_code(NULL),
135 imclass_imports(NULL),
136 module_imports(NULL),
137 imclass_baseclass(NULL),
138 module_baseclass(NULL),
139 imclass_interfaces(NULL),
140 module_interfaces(NULL),
141 imclass_class_modifiers(NULL),
142 module_class_modifiers(NULL),
144 imclass_cppcasts_code(NULL),
145 imclass_directors(NULL),
146 destructor_call(NULL),
147 destructor_throws_clause(NULL),
149 dmethods_table(NULL),
152 /* for now, multiple inheritance in directors is disabled, this
153 should be easy to implement though */
154 director_multiple_inheritance = 0;
155 director_language = 1;
158 /* -----------------------------------------------------------------------------
161 * Test to see if a type corresponds to something wrapped with a proxy class
162 * Return NULL if not otherwise the proxy class name
163 * ----------------------------------------------------------------------------- */
165 String *getProxyName(SwigType *t) {
167 Node *n = classLookup(t);
169 return Getattr(n, "sym:name");
175 /* -----------------------------------------------------------------------------
177 * ----------------------------------------------------------------------------- */
179 String *makeValidJniName(const String *name) {
180 String *valid_jni_name = NewString(name);
181 Replaceall(valid_jni_name, "_", "_1");
182 return valid_jni_name;
185 /* -----------------------------------------------------------------------------
186 * directorClassName()
187 * ----------------------------------------------------------------------------- */
189 String *directorClassName(Node *n) {
190 String *dirclassname;
191 const char *attrib = "director:classname";
193 if (!(dirclassname = Getattr(n, attrib))) {
194 String *classname = Getattr(n, "sym:name");
196 dirclassname = NewStringf("SwigDirector_%s", classname);
197 Setattr(n, attrib, dirclassname);
203 /* ------------------------------------------------------------
205 * ------------------------------------------------------------ */
207 virtual void main(int argc, char *argv[]) {
209 SWIG_library_directory("java");
211 // Look for certain command line options
212 for (int i = 1; i < argc; i++) {
214 if (strcmp(argv[i], "-package") == 0) {
216 package = NewString("");
217 Printf(package, argv[i + 1]);
219 Swig_mark_arg(i + 1);
224 } else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
225 Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]);
228 } else if ((strcmp(argv[i], "-noproxy") == 0)) {
231 } else if (strcmp(argv[i], "-nopgcpp") == 0) {
234 } else if (strcmp(argv[i], "-oldvarnames") == 0) {
236 old_variable_names = true;
237 } else if (strcmp(argv[i], "-jnic") == 0) {
239 Printf(stderr, "Deprecated command line option: -jnic. C JNI calling convention now used when -c++ not specified.\n");
240 } else if (strcmp(argv[i], "-nofinalize") == 0) {
242 Printf(stderr, "Deprecated command line option: -nofinalize. Use the new javafinalize typemap instead.\n");
243 } else if (strcmp(argv[i], "-jnicpp") == 0) {
245 Printf(stderr, "Deprecated command line option: -jnicpp. C++ JNI calling convention now used when -c++ specified.\n");
246 } else if (strcmp(argv[i], "-help") == 0) {
247 Printf(stdout, "%s\n", usage);
252 // Add a symbol to the parser for conditional compilation
253 Preprocessor_define("SWIGJAVA 1", 0);
255 // Add typemap definitions
256 SWIG_typemap_lang("java");
257 SWIG_config_file("java.swg");
262 /* ---------------------------------------------------------------------
264 * --------------------------------------------------------------------- */
266 virtual int top(Node *n) {
268 // Get any options set in the module directive
269 Node *optionsnode = Getattr(Getattr(n, "module"), "options");
272 if (Getattr(optionsnode, "jniclassname"))
273 imclass_name = Copy(Getattr(optionsnode, "jniclassname"));
274 /* check if directors are enabled for this module. note: this
275 * is a "master" switch, without which no director code will be
276 * emitted. %feature("director") statements are also required
277 * to enable directors for individual classes or methods.
279 * use %module(directors="1") modulename at the start of the
280 * interface file to enable director generation.
282 if (Getattr(optionsnode, "directors")) {
285 if (Getattr(optionsnode, "dirprot")) {
288 allow_allprotected(GetFlag(optionsnode, "allprotected"));
291 /* Initialize all of the output files */
292 String *outfile = Getattr(n, "outfile");
293 String *outfile_h = Getattr(n, "outfile_h");
296 Printf(stderr, "Unable to determine outfile\n");
297 SWIG_exit(EXIT_FAILURE);
300 f_begin = NewFile(outfile, "w", SWIG_output_files());
302 FileErrorDisplay(outfile);
303 SWIG_exit(EXIT_FAILURE);
306 if (directorsEnabled()) {
308 Printf(stderr, "Unable to determine outfile_h\n");
309 SWIG_exit(EXIT_FAILURE);
311 f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
313 FileErrorDisplay(outfile_h);
314 SWIG_exit(EXIT_FAILURE);
318 f_runtime = NewString("");
319 f_init = NewString("");
320 f_header = NewString("");
321 f_wrappers = NewString("");
322 f_directors_h = NewString("");
323 f_directors = NewString("");
325 /* Register file targets with the SWIG file handler */
326 Swig_register_filebyname("begin", f_begin);
327 Swig_register_filebyname("header", f_header);
328 Swig_register_filebyname("wrapper", f_wrappers);
329 Swig_register_filebyname("runtime", f_runtime);
330 Swig_register_filebyname("init", f_init);
331 Swig_register_filebyname("director", f_directors);
332 Swig_register_filebyname("director_h", f_directors_h);
334 swig_types_hash = NewHash();
335 filenames_list = NewList();
337 // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
339 imclass_name = NewStringf("%sJNI", Getattr(n, "name"));
340 module_class_name = Copy(Getattr(n, "name"));
342 // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
343 if (Cmp(imclass_name, Getattr(n, "name")) == 0)
344 module_class_name = NewStringf("%sModule", Getattr(n, "name"));
346 module_class_name = Copy(Getattr(n, "name"));
349 imclass_class_code = NewString("");
350 proxy_class_def = NewString("");
351 proxy_class_code = NewString("");
352 module_class_constants_code = NewString("");
353 imclass_baseclass = NewString("");
354 imclass_interfaces = NewString("");
355 imclass_class_modifiers = NewString("");
356 module_class_code = NewString("");
357 module_baseclass = NewString("");
358 module_interfaces = NewString("");
359 module_imports = NewString("");
360 module_class_modifiers = NewString("");
361 imclass_imports = NewString("");
362 imclass_cppcasts_code = NewString("");
363 imclass_directors = NewString("");
364 upcasts_code = NewString("");
365 dmethods_seq = NewList();
366 dmethods_table = NewHash();
370 package = NewString("");
371 jnipackage = NewString("");
372 package_path = NewString("");
374 Swig_banner(f_begin);
376 Printf(f_runtime, "\n#define SWIGJAVA\n");
378 if (directorsEnabled()) {
379 Printf(f_runtime, "#define SWIG_DIRECTORS\n");
381 /* Emit initial director header and director code: */
382 Swig_banner(f_directors_h);
383 Printf(f_directors_h, "\n");
384 Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
385 Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
387 Printf(f_directors, "\n\n");
388 Printf(f_directors, "/* ---------------------------------------------------\n");
389 Printf(f_directors, " * C++ director class methods\n");
390 Printf(f_directors, " * --------------------------------------------------- */\n\n");
392 Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
395 Printf(f_runtime, "\n");
397 String *wrapper_name = NewString("");
400 String *jniname = makeValidJniName(package);
401 Printv(jnipackage, jniname, NIL);
403 Replaceall(jnipackage, ".", "_");
404 Append(jnipackage, "_");
405 Printv(package_path, package, NIL);
406 Replaceall(package_path, ".", "/");
408 String *jniname = makeValidJniName(imclass_name);
409 Printf(wrapper_name, "Java_%s%s_%%f", Char(jnipackage), jniname);
412 Swig_name_register((char *) "wrapper", Char(wrapper_name));
413 if (old_variable_names) {
414 Swig_name_register((char *) "set", (char *) "set_%v");
415 Swig_name_register((char *) "get", (char *) "get_%v");
418 Delete(wrapper_name);
420 Printf(f_wrappers, "\n#ifdef __cplusplus\n");
421 Printf(f_wrappers, "extern \"C\" {\n");
422 Printf(f_wrappers, "#endif\n\n");
427 if (directorsEnabled()) {
428 // Insert director runtime into the f_runtime file (make it occur before %header section)
429 Swig_insert_file("director.swg", f_runtime);
431 // Generate the intermediary class
433 String *filen = NewStringf("%s%s.java", SWIG_output_directory(), imclass_name);
434 File *f_im = NewFile(filen, "w", SWIG_output_files());
436 FileErrorDisplay(filen);
437 SWIG_exit(EXIT_FAILURE);
439 Append(filenames_list, Copy(filen));
443 // Start writing out the intermediary class file
446 if (Len(package) > 0)
447 Printf(f_im, "package %s;\n", package);
450 Printf(f_im, "%s\n", imclass_imports);
452 if (Len(imclass_class_modifiers) > 0)
453 Printf(f_im, "%s ", imclass_class_modifiers);
454 Printf(f_im, "%s ", imclass_name);
456 if (imclass_baseclass && *Char(imclass_baseclass))
457 Printf(f_im, "extends %s ", imclass_baseclass);
458 if (Len(imclass_interfaces) > 0)
459 Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
462 // Add the intermediary class methods
463 Replaceall(imclass_class_code, "$module", module_class_name);
464 Replaceall(imclass_class_code, "$imclassname", imclass_name);
465 Printv(f_im, imclass_class_code, NIL);
466 Printv(f_im, imclass_cppcasts_code, NIL);
467 if (Len(imclass_directors) > 0)
468 Printv(f_im, "\n", imclass_directors, NIL);
470 if (n_dmethods > 0) {
472 Printf(f_im, " private final static native void swig_module_init();\n");
473 Printf(f_im, " static {\n");
474 Printf(f_im, " swig_module_init();\n");
475 Printf(f_im, " }\n");
477 // Finish off the class
482 // Generate the Java module class
484 String *filen = NewStringf("%s%s.java", SWIG_output_directory(), module_class_name);
485 File *f_module = NewFile(filen, "w", SWIG_output_files());
487 FileErrorDisplay(filen);
488 SWIG_exit(EXIT_FAILURE);
490 Append(filenames_list, Copy(filen));
494 // Start writing out the module class file
495 emitBanner(f_module);
497 if (Len(package) > 0)
498 Printf(f_module, "package %s;\n", package);
501 Printf(f_module, "%s\n", module_imports);
503 if (Len(module_class_modifiers) > 0)
504 Printf(f_module, "%s ", module_class_modifiers);
505 Printf(f_module, "%s ", module_class_name);
507 if (module_baseclass && *Char(module_baseclass))
508 Printf(f_module, "extends %s ", module_baseclass);
509 if (Len(module_interfaces) > 0) {
510 if (Len(module_class_constants_code) != 0)
511 Printv(f_module, "implements ", Getattr(n, "name"), "Constants, ", module_interfaces, " ", NIL);
513 Printv(f_module, "implements ", module_interfaces, " ", NIL);
515 if (Len(module_class_constants_code) != 0)
516 Printv(f_module, "implements ", Getattr(n, "name"), "Constants ", NIL);
518 Printf(f_module, "{\n");
520 Replaceall(module_class_code, "$module", module_class_name);
521 Replaceall(module_class_constants_code, "$module", module_class_name);
523 Replaceall(module_class_code, "$imclassname", imclass_name);
524 Replaceall(module_class_constants_code, "$imclassname", imclass_name);
526 // Add the wrapper methods
527 Printv(f_module, module_class_code, NIL);
529 // Finish off the class
530 Printf(f_module, "}\n");
534 // Generate the Java constants interface
535 if (Len(module_class_constants_code) != 0) {
536 String *filen = NewStringf("%s%sConstants.java", SWIG_output_directory(), module_class_name);
537 File *f_module = NewFile(filen, "w", SWIG_output_files());
539 FileErrorDisplay(filen);
540 SWIG_exit(EXIT_FAILURE);
542 Append(filenames_list, Copy(filen));
546 // Start writing out the Java constants interface file
547 emitBanner(f_module);
549 if (Len(package) > 0)
550 Printf(f_module, "package %s;\n", package);
553 Printf(f_module, "%s\n", module_imports);
555 Printf(f_module, "public interface %sConstants {\n", module_class_name);
557 // Write out all the global constants
558 Printv(f_module, module_class_constants_code, NIL);
560 // Finish off the Java interface
561 Printf(f_module, "}\n");
566 Printv(f_wrappers, upcasts_code, NIL);
568 emitDirectorUpcalls();
570 Printf(f_wrappers, "#ifdef __cplusplus\n");
571 Printf(f_wrappers, "}\n");
572 Printf(f_wrappers, "#endif\n");
574 // Output a Java type wrapper class for each SWIG type
575 for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
576 emitTypeWrapperClass(swig_type.key, swig_type.item);
579 // Check for overwriting file problems on filesystems that are case insensitive
582 for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
583 String *item1_lower = Swig_string_lower(it1.item);
584 for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
585 String *item2_lower = Swig_string_lower(it2.item);
586 if (it1.item && it2.item) {
587 if (Strcmp(item1_lower, item2_lower) == 0) {
588 Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
589 "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
590 "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
598 Delete(swig_types_hash);
599 swig_types_hash = NULL;
600 Delete(filenames_list);
601 filenames_list = NULL;
602 Delete(imclass_name);
604 Delete(imclass_class_code);
605 imclass_class_code = NULL;
606 Delete(proxy_class_def);
607 proxy_class_def = NULL;
608 Delete(proxy_class_code);
609 proxy_class_code = NULL;
610 Delete(module_class_constants_code);
611 module_class_constants_code = NULL;
612 Delete(imclass_baseclass);
613 imclass_baseclass = NULL;
614 Delete(imclass_interfaces);
615 imclass_interfaces = NULL;
616 Delete(imclass_class_modifiers);
617 imclass_class_modifiers = NULL;
618 Delete(module_class_name);
619 module_class_name = NULL;
620 Delete(module_class_code);
621 module_class_code = NULL;
622 Delete(module_baseclass);
623 module_baseclass = NULL;
624 Delete(module_interfaces);
625 module_interfaces = NULL;
626 Delete(module_imports);
627 module_imports = NULL;
628 Delete(module_class_modifiers);
629 module_class_modifiers = NULL;
630 Delete(imclass_imports);
631 imclass_imports = NULL;
632 Delete(imclass_cppcasts_code);
633 imclass_cppcasts_code = NULL;
634 Delete(imclass_directors);
635 imclass_directors = NULL;
636 Delete(upcasts_code);
642 Delete(package_path);
644 Delete(dmethods_seq);
646 Delete(dmethods_table);
647 dmethods_table = NULL;
650 /* Close all of the files */
651 Dump(f_header, f_runtime);
653 if (directorsEnabled()) {
654 Dump(f_directors, f_runtime);
655 Dump(f_directors_h, f_runtime_h);
657 Printf(f_runtime_h, "\n");
658 Printf(f_runtime_h, "#endif\n");
665 Delete(f_directors_h);
666 f_directors_h = NULL;
669 Dump(f_wrappers, f_runtime);
670 Wrapper_pretty_print(f_init, f_runtime);
674 Dump(f_runtime, f_begin);
681 /* -----------------------------------------------------------------------------
683 * ----------------------------------------------------------------------------- */
685 void emitBanner(File *f) {
686 Printf(f, "/* ----------------------------------------------------------------------------\n");
687 Swig_banner_target_lang(f, " *");
688 Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
691 /*-----------------------------------------------------------------------
692 * Add new director upcall signature
693 *----------------------------------------------------------------------*/
695 UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *imclass_desc, String *class_desc, String *decl) {
697 String *imclass_methodidx;
698 String *class_methodidx;
700 String *key = NewStringf("%s|%s", imclass_method, decl);
702 ++curr_class_dmethod;
704 /* Do we know about this director class already? */
705 if ((udata = Getattr(dmethods_table, key))) {
707 return Getattr(udata, "methodoff");
710 imclass_methodidx = NewStringf("%d", n_dmethods);
711 class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
714 new_udata = NewHash();
715 Append(dmethods_seq, new_udata);
716 Setattr(dmethods_table, key, new_udata);
718 Setattr(new_udata, "method", Copy(class_method));
719 Setattr(new_udata, "fdesc", Copy(class_desc));
720 Setattr(new_udata, "imclass_method", Copy(imclass_method));
721 Setattr(new_udata, "imclass_fdesc", Copy(imclass_desc));
722 Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
723 Setattr(new_udata, "class_methodidx", class_methodidx);
724 Setattr(new_udata, "decl", Copy(decl));
730 /*-----------------------------------------------------------------------
731 * Get director upcall signature
732 *----------------------------------------------------------------------*/
734 UpcallData *getUpcallMethodData(String *director_class, String *decl) {
735 String *key = NewStringf("%s|%s", director_class, decl);
736 UpcallData *udata = Getattr(dmethods_table, key);
742 /* ----------------------------------------------------------------------
744 * ---------------------------------------------------------------------- */
746 virtual int nativeWrapper(Node *n) {
747 String *wrapname = Getattr(n, "wrap:name");
749 if (!addSymbol(wrapname, n))
752 if (Getattr(n, "type")) {
753 Swig_save("nativeWrapper", n, "name", NIL);
754 Setattr(n, "name", wrapname);
755 native_function_flag = true;
758 native_function_flag = false;
760 Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n, "wrap:name"));
766 /* ----------------------------------------------------------------------
768 * ---------------------------------------------------------------------- */
770 virtual int functionWrapper(Node *n) {
771 String *symname = Getattr(n, "sym:name");
772 SwigType *t = Getattr(n, "type");
773 ParmList *l = Getattr(n, "parms");
777 String *c_return_type = NewString("");
778 String *im_return_type = NewString("");
779 String *cleanup = NewString("");
780 String *outarg = NewString("");
781 String *body = NewString("");
782 int num_arguments = 0;
783 int num_required = 0;
786 String *overloaded_name = getOverloadedName(n);
787 String *nondir_args = NewString("");
788 bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0);
790 if (!Getattr(n, "sym:overloaded")) {
791 if (!addSymbol(Getattr(n, "sym:name"), n))
796 The rest of this function deals with generating the intermediary class wrapper function (that wraps
797 a c/c++ function) and generating the JNI c code. Each Java wrapper function has a
798 matching JNI c function call.
801 // A new wrapper function object
802 Wrapper *f = NewWrapper();
804 // Make a wrapper name for this function
805 String *jniname = makeValidJniName(overloaded_name);
806 String *wname = Swig_name_wrapper(jniname);
810 /* Attach the non-standard typemaps to the parameter list. */
811 Swig_typemap_attach_parms("jni", l, f);
812 Swig_typemap_attach_parms("jtype", l, f);
813 Swig_typemap_attach_parms("jstype", l, f);
815 /* Get return types */
816 if ((tm = Swig_typemap_lookup("jni", n, "", 0))) {
817 Printf(c_return_type, "%s", tm);
819 Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(t, 0));
822 if ((tm = Swig_typemap_lookup("jtype", n, "", 0))) {
823 Printf(im_return_type, "%s", tm);
825 Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(t, 0));
828 is_void_return = (Cmp(c_return_type, "void") == 0);
830 Wrapper_add_localv(f, "jresult", c_return_type, "jresult = 0", NIL);
832 Printv(f->def, "SWIGEXPORT ", c_return_type, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL);
834 // Usually these function parameters are unused - The code below ensures
835 // that compilers do not issue such a warning if configured to do so.
837 Printv(f->code, " (void)jenv;\n", NIL);
838 Printv(f->code, " (void)jcls;\n", NIL);
840 // Emit all of the local variables for holding arguments.
841 emit_parameter_variables(l, f);
843 /* Attach the standard typemaps */
844 emit_attach_parmmaps(l, f);
846 // Parameter overloading
847 Setattr(n, "wrap:parms", l);
848 Setattr(n, "wrap:name", wname);
850 // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
851 if (Getattr(n, "sym:overloaded")) {
852 // Emit warnings for the few cases that can't be overloaded in Java and give up on generating wrapper
853 Swig_overload_check(n);
854 if (Getattr(n, "overload:ignore"))
858 Printf(imclass_class_code, " public final static native %s %s(", im_return_type, overloaded_name);
860 /* Get number of required and total arguments */
861 num_arguments = emit_num_arguments(l);
862 num_required = emit_num_required(l);
864 // Now walk the function parameter list and generate code to get arguments
865 for (i = 0, p = l; i < num_arguments; i++) {
867 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
868 p = Getattr(p, "tmap:in:next");
871 SwigType *pt = Getattr(p, "type");
872 String *ln = Getattr(p, "lname");
873 String *im_param_type = NewString("");
874 String *c_param_type = NewString("");
875 String *arg = NewString("");
877 Printf(arg, "j%s", ln);
879 /* Get the JNI C types of the parameter */
880 if ((tm = Getattr(p, "tmap:jni"))) {
881 Printv(c_param_type, tm, NIL);
883 Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0));
886 /* Get the intermediary class parameter types of the parameter */
887 if ((tm = Getattr(p, "tmap:jtype"))) {
888 Printv(im_param_type, tm, NIL);
890 Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0));
893 /* Add parameter to intermediary class method */
895 Printf(imclass_class_code, ", ");
896 Printf(imclass_class_code, "%s %s", im_param_type, arg);
898 // Add parameter to C function
899 Printv(f->def, ", ", c_param_type, " ", arg, NIL);
903 // Premature garbage collection prevention parameter
904 if (!is_destructor) {
905 String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p);
907 Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg);
908 Printf(f->def, ", jobject %s_", arg);
909 Printf(f->code, " (void)%s_;\n", arg);
912 // Get typemap for this argument
913 if ((tm = Getattr(p, "tmap:in"))) {
914 addThrows(n, "tmap:in", p);
915 Replaceall(tm, "$source", arg); /* deprecated */
916 Replaceall(tm, "$target", ln); /* deprecated */
917 Replaceall(tm, "$arg", arg); /* deprecated? */
918 Replaceall(tm, "$input", arg);
919 Setattr(p, "emit:input", arg);
921 Printf(nondir_args, "%s\n", tm);
923 p = Getattr(p, "tmap:in:next");
925 Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
929 Delete(im_param_type);
930 Delete(c_param_type);
934 Printv(f->code, nondir_args, NIL);
937 /* Insert constraint checking code */
939 if ((tm = Getattr(p, "tmap:check"))) {
940 addThrows(n, "tmap:check", p);
941 Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
942 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
943 Replaceall(tm, "$input", Getattr(p, "emit:input"));
944 Printv(f->code, tm, "\n", NIL);
945 p = Getattr(p, "tmap:check:next");
951 /* Insert cleanup code */
953 if ((tm = Getattr(p, "tmap:freearg"))) {
954 addThrows(n, "tmap:freearg", p);
955 Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
956 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
957 Replaceall(tm, "$input", Getattr(p, "emit:input"));
958 Printv(cleanup, tm, "\n", NIL);
959 p = Getattr(p, "tmap:freearg:next");
965 /* Insert argument output code */
967 if ((tm = Getattr(p, "tmap:argout"))) {
968 addThrows(n, "tmap:argout", p);
969 Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
970 Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
971 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
972 Replaceall(tm, "$result", "jresult");
973 Replaceall(tm, "$input", Getattr(p, "emit:input"));
974 Printv(outarg, tm, "\n", NIL);
975 p = Getattr(p, "tmap:argout:next");
981 // Get any Java exception classes in the throws typemap
982 ParmList *throw_parm_list = NULL;
983 if ((throw_parm_list = Getattr(n, "catchlist"))) {
984 Swig_typemap_attach_parms("throws", throw_parm_list, f);
985 for (p = throw_parm_list; p; p = nextSibling(p)) {
986 if ((tm = Getattr(p, "tmap:throws"))) {
987 addThrows(n, "tmap:throws", p);
992 if (!native_function_flag) {
993 if (Cmp(nodeType(n), "constant") == 0) {
994 // Wrapping a constant hack
995 Swig_save("functionWrapper", n, "wrap:action", NIL);
997 // below based on Swig_VargetToFunction()
998 SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
999 Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
1002 // Now write code to make the function call
1003 Swig_director_emit_dynamic_cast(n, f);
1004 String *actioncode = emit_action(n);
1006 // Handle exception classes specified in the "except" feature's "throws" attribute
1007 addThrows(n, "feature:except", n);
1009 if (Cmp(nodeType(n), "constant") == 0)
1012 /* Return value if necessary */
1013 if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
1014 addThrows(n, "tmap:out", n);
1015 Replaceall(tm, "$source", "result"); /* deprecated */
1016 Replaceall(tm, "$target", "jresult"); /* deprecated */
1017 Replaceall(tm, "$result", "jresult");
1019 if (GetFlag(n, "feature:new"))
1020 Replaceall(tm, "$owner", "1");
1022 Replaceall(tm, "$owner", "0");
1024 Printf(f->code, "%s", tm);
1026 Printf(f->code, "\n");
1028 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"));
1030 emit_return_variable(n, t, f);
1033 /* Output argument output code */
1034 Printv(f->code, outarg, NIL);
1036 /* Output cleanup code */
1037 Printv(f->code, cleanup, NIL);
1039 /* Look to see if there is any newfree cleanup code */
1040 if (GetFlag(n, "feature:new")) {
1041 if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
1042 addThrows(n, "tmap:newfree", n);
1043 Replaceall(tm, "$source", "result"); /* deprecated */
1044 Printf(f->code, "%s\n", tm);
1048 /* See if there is any return cleanup code */
1049 if (!native_function_flag) {
1050 if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
1051 addThrows(n, "tmap:ret", n);
1052 Replaceall(tm, "$source", "result"); /* deprecated */
1053 Printf(f->code, "%s\n", tm);
1057 /* Finish C function and intermediary class function definitions */
1058 Printf(imclass_class_code, ")");
1059 generateThrowsClause(n, imclass_class_code);
1060 Printf(imclass_class_code, ";\n");
1062 Printf(f->def, ") {");
1064 if (!is_void_return)
1065 Printv(f->code, " return jresult;\n", NIL);
1066 Printf(f->code, "}\n");
1068 /* Substitute the cleanup code */
1069 Replaceall(f->code, "$cleanup", cleanup);
1071 /* Substitute the function name */
1072 Replaceall(f->code, "$symname", symname);
1074 /* Contract macro modification */
1075 Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
1077 if (!is_void_return)
1078 Replaceall(f->code, "$null", "0");
1080 Replaceall(f->code, "$null", "");
1082 /* Dump the function out */
1083 if (!native_function_flag)
1084 Wrapper_print(f, f_wrappers);
1086 if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1087 moduleClassFunctionHandler(n);
1091 * Generate the proxy class getters/setters for public member variables.
1092 * Not for enums and constants.
1094 if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1095 // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
1096 bool getter_flag = Cmp(symname, Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) != 0;
1098 String *getter_setter_name = NewString("");
1100 Printf(getter_setter_name, "set");
1102 Printf(getter_setter_name, "get");
1103 Putc(toupper((int) *Char(variable_name)), getter_setter_name);
1104 Printf(getter_setter_name, "%s", Char(variable_name) + 1);
1106 Setattr(n, "proxyfuncname", getter_setter_name);
1107 Setattr(n, "imfuncname", symname);
1109 proxyClassFunctionHandler(n);
1110 Delete(getter_setter_name);
1113 Delete(c_return_type);
1114 Delete(im_return_type);
1118 Delete(overloaded_name);
1123 /* -----------------------------------------------------------------------
1125 * ----------------------------------------------------------------------- */
1127 virtual int variableWrapper(Node *n) {
1128 variable_wrapper_flag = true;
1129 Language::variableWrapper(n); /* Default to functions */
1130 variable_wrapper_flag = false;
1134 /* -----------------------------------------------------------------------
1135 * globalvariableHandler()
1136 * ------------------------------------------------------------------------ */
1138 virtual int globalvariableHandler(Node *n) {
1140 variable_name = Getattr(n, "sym:name");
1141 global_variable_flag = true;
1142 int ret = Language::globalvariableHandler(n);
1143 global_variable_flag = false;
1147 /* ----------------------------------------------------------------------
1150 * C/C++ enums can be mapped in one of 4 ways, depending on the java:enum feature specified:
1151 * 1) Simple enums - simple constant within the proxy class or module class
1152 * 2) Typeunsafe enums - simple constant in a Java class (class named after the c++ enum name)
1153 * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
1154 * 4) Proper enums - proper Java enum
1155 * Anonymous enums always default to 1)
1156 * ---------------------------------------------------------------------- */
1158 virtual int enumDeclaration(Node *n) {
1161 if (getCurrentClass() && (cplus_mode != PUBLIC))
1164 enum_code = NewString("");
1165 String *symname = Getattr(n, "sym:name");
1166 String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
1167 EnumFeature enum_feature = decodeEnumFeature(n);
1168 String *typemap_lookup_type = Getattr(n, "name");
1170 if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1171 // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
1173 // Pure Java baseclass and interfaces
1174 const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE);
1175 const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
1178 Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers (enum modifiers really)
1179 " ", symname, *Char(pure_baseclass) ? // Bases
1180 " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
1181 " implements " : "", pure_interfaces, " {\n", NIL);
1182 if (proxy_flag && is_wrapping_class())
1183 Replaceall(enum_code, "$static ", "static ");
1185 Replaceall(enum_code, "$static ", "");
1187 // Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
1188 if (symname && !Getattr(n, "unnamedinstance"))
1189 Printf(constants_code, " // %s \n", symname);
1192 // Emit each enum item
1193 Language::enumDeclaration(n);
1195 if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1196 // Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
1197 // Finish the enum declaration
1198 // Typemaps are used to generate the enum definition in a similar manner to proxy classes.
1199 Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
1200 typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
1203 Replaceall(enum_code, "$javaclassname", symname);
1205 // Substitute $enumvalues - intended usage is for typesafe enums
1206 if (Getattr(n, "enumvalues"))
1207 Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
1209 Replaceall(enum_code, "$enumvalues", "");
1211 if (proxy_flag && is_wrapping_class()) {
1212 // Enums defined within the C++ class are defined within the proxy class
1214 // Add extra indentation
1215 Replaceall(enum_code, "\n", "\n ");
1216 Replaceall(enum_code, " \n", "\n");
1218 Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
1220 // Global enums are defined in their own file
1221 String *filen = NewStringf("%s%s.java", SWIG_output_directory(), symname);
1222 File *f_enum = NewFile(filen, "w", SWIG_output_files());
1224 FileErrorDisplay(filen);
1225 SWIG_exit(EXIT_FAILURE);
1227 Append(filenames_list, Copy(filen));
1231 // Start writing out the enum file
1234 if (Len(package) > 0)
1235 Printf(f_enum, "package %s;\n", package);
1237 Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
1238 "\n", enum_code, "\n", NIL);
1240 Printf(f_enum, "\n");
1244 // Wrap C++ enum with simple constant
1245 Printf(enum_code, "\n");
1246 if (proxy_flag && is_wrapping_class())
1247 Printv(proxy_class_constants_code, enum_code, NIL);
1249 Printv(module_class_constants_code, enum_code, NIL);
1258 /* ----------------------------------------------------------------------
1259 * enumvalueDeclaration()
1260 * ---------------------------------------------------------------------- */
1262 virtual int enumvalueDeclaration(Node *n) {
1263 if (getCurrentClass() && (cplus_mode != PUBLIC))
1266 Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
1267 String *symname = Getattr(n, "sym:name");
1268 String *value = Getattr(n, "value");
1269 String *name = Getattr(n, "name");
1272 // Strange hack from parent method
1274 tmpValue = NewString(value);
1276 tmpValue = NewString(name);
1277 // Note that this is used in enumValue() amongst other places
1278 Setattr(n, "value", tmpValue);
1281 EnumFeature enum_feature = decodeEnumFeature(parentNode(n));
1283 if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1284 // Wrap (non-anonymous) C/C++ enum with a proper Java enum
1285 // Emit the enum item.
1286 if (!GetFlag(n, "firstenumitem"))
1287 Printf(enum_code, ",\n");
1288 Printf(enum_code, " %s", symname);
1289 if (Getattr(n, "enumvalue")) {
1290 String *value = enumValue(n);
1291 Printf(enum_code, "(%s)", value);
1295 // Wrap C/C++ enums with constant integers or use the typesafe enum pattern
1296 const String *parent_name = Getattr(parentNode(n), "name");
1297 String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int");
1298 const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF);
1299 String *return_type = Copy(tm);
1300 Delete(typemap_lookup_type);
1301 typemap_lookup_type = NULL;
1303 const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1304 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1306 if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1307 // Wrap (non-anonymouse) enum using the typesafe enum pattern
1308 if (Getattr(n, "enumvalue")) {
1309 String *value = enumValue(n);
1310 Printf(enum_code, " %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
1313 Printf(enum_code, " %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
1316 // Simple integer constants
1317 // Note these are always generated for anonymous enums, no matter what enum_feature is specified
1318 // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
1319 String *value = enumValue(n);
1320 Printf(enum_code, " %s final static %s %s = %s;\n", methodmods, return_type, symname, value);
1325 // Add the enum value to the comma separated list being constructed in the enum declaration.
1326 String *enumvalues = Getattr(parentNode(n), "enumvalues");
1328 Setattr(parentNode(n), "enumvalues", Copy(symname));
1330 Printv(enumvalues, ", ", symname, NIL);
1338 /* -----------------------------------------------------------------------
1340 * Used for wrapping constants - #define or %constant.
1341 * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
1342 * Java static final variables are generated for these.
1343 * If the %javaconst(1) feature is used then the C constant value is used to initialise the Java final variable.
1344 * If not, a JNI method is generated to get the C constant value for initialisation of the Java final variable.
1345 * However, if the %javaconstvalue feature is used, it overrides all other ways to generate the initialisation.
1346 * Also note that this method might be called for wrapping enum items (when the enum is using %javaconst(0)).
1347 * ------------------------------------------------------------------------ */
1349 virtual int constantWrapper(Node *n) {
1350 String *symname = Getattr(n, "sym:name");
1351 SwigType *t = Getattr(n, "type");
1352 ParmList *l = Getattr(n, "parms");
1354 String *return_type = NewString("");
1355 String *constants_code = NewString("");
1357 if (!addSymbol(symname, n))
1360 bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
1362 // The %javaconst feature determines how the constant value is obtained
1363 int const_feature_flag = GetFlag(n, "feature:java:const");
1365 /* Adjust the enum type for the Swig_typemap_lookup.
1366 * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
1368 t = Getattr(parentNode(n), "enumtype");
1369 Setattr(n, "type", t);
1372 /* Attach the non-standard typemaps to the parameter list. */
1373 Swig_typemap_attach_parms("jstype", l, NULL);
1375 /* Get Java return types */
1376 bool classname_substituted_flag = false;
1378 if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
1379 classname_substituted_flag = substituteClassname(t, tm);
1380 Printf(return_type, "%s", tm);
1382 Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
1385 // Add the stripped quotes back in
1386 String *new_value = NewString("");
1387 Swig_save("constantWrapper", n, "value", NIL);
1388 if (SwigType_type(t) == T_STRING) {
1389 Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
1390 Setattr(n, "value", new_value);
1391 } else if (SwigType_type(t) == T_CHAR) {
1392 Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
1393 Setattr(n, "value", new_value);
1396 const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
1397 const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1398 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1400 Printf(constants_code, " %s final static %s %s = ", methodmods, return_type, itemname);
1402 // Check for the %javaconstvalue feature
1403 String *value = Getattr(n, "feature:java:constvalue");
1406 Printf(constants_code, "%s;\n", value);
1407 } else if (!const_feature_flag) {
1408 // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call.
1410 if (classname_substituted_flag) {
1411 if (SwigType_isenum(t)) {
1412 // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
1413 Printf(constants_code, "%s.swigToEnum(%s.%s());\n", return_type, imclass_name, Swig_name_get(symname));
1415 // This handles function pointers using the %constant directive
1416 Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
1419 Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname));
1421 // Each constant and enum value is wrapped with a separate JNI function call
1422 SetFlag(n, "feature:immutable");
1423 enum_constant_flag = true;
1425 enum_constant_flag = false;
1427 // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code
1428 Printf(constants_code, "%s;\n", Getattr(n, "value"));
1431 // Emit the generated code to appropriate place
1432 // Enums only emit the intermediate and JNI methods, so no proxy or module class wrapper methods needed
1433 if (!is_enum_item) {
1434 if (proxy_flag && wrapping_member_flag)
1435 Printv(proxy_class_constants_code, constants_code, NIL);
1437 Printv(module_class_constants_code, constants_code, NIL);
1442 Delete(return_type);
1443 Delete(constants_code);
1447 /* -----------------------------------------------------------------------------
1449 * ----------------------------------------------------------------------------- */
1451 virtual int insertDirective(Node *n) {
1452 String *code = Getattr(n, "code");
1453 Replaceall(code, "$module", module_class_name);
1454 Replaceall(code, "$imclassname", imclass_name);
1455 return Language::insertDirective(n);
1458 /* -----------------------------------------------------------------------------
1462 * jniclassbase - base (extends) for the intermediary class
1463 * jniclassclassmodifiers - class modifiers for the intermediary class
1464 * jniclasscode - text (java code) is copied verbatim to the intermediary class
1465 * jniclassimports - import statements for the intermediary class
1466 * jniclassinterfaces - interface (implements) for the intermediary class
1468 * modulebase - base (extends) for the module class
1469 * moduleclassmodifiers - class modifiers for the module class
1470 * modulecode - text (java code) is copied verbatim to the module class
1471 * moduleimports - import statements for the module class
1472 * moduleinterfaces - interface (implements) for the module class
1474 * ----------------------------------------------------------------------------- */
1476 virtual int pragmaDirective(Node *n) {
1478 String *lang = Getattr(n, "lang");
1479 String *code = Getattr(n, "name");
1480 String *value = Getattr(n, "value");
1482 if (Strcmp(lang, "java") == 0) {
1484 String *strvalue = NewString(value);
1485 Replaceall(strvalue, "\\\"", "\"");
1487 if (Strcmp(code, "jniclassbase") == 0) {
1488 Delete(imclass_baseclass);
1489 imclass_baseclass = Copy(strvalue);
1490 } else if (Strcmp(code, "jniclassclassmodifiers") == 0) {
1491 Delete(imclass_class_modifiers);
1492 imclass_class_modifiers = Copy(strvalue);
1493 } else if (Strcmp(code, "jniclasscode") == 0) {
1494 Printf(imclass_class_code, "%s\n", strvalue);
1495 } else if (Strcmp(code, "jniclassimports") == 0) {
1496 Delete(imclass_imports);
1497 imclass_imports = Copy(strvalue);
1498 } else if (Strcmp(code, "jniclassinterfaces") == 0) {
1499 Delete(imclass_interfaces);
1500 imclass_interfaces = Copy(strvalue);
1501 } else if (Strcmp(code, "modulebase") == 0) {
1502 Delete(module_baseclass);
1503 module_baseclass = Copy(strvalue);
1504 } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
1505 Delete(module_class_modifiers);
1506 module_class_modifiers = Copy(strvalue);
1507 } else if (Strcmp(code, "modulecode") == 0) {
1508 Printf(module_class_code, "%s\n", strvalue);
1509 } else if (Strcmp(code, "moduleimports") == 0) {
1510 Delete(module_imports);
1511 module_imports = Copy(strvalue);
1512 } else if (Strcmp(code, "moduleinterfaces") == 0) {
1513 Delete(module_interfaces);
1514 module_interfaces = Copy(strvalue);
1515 } else if (Strcmp(code, "moduleimport") == 0) {
1516 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use the moduleimports pragma.\n", input_file, line_number);
1517 } else if (Strcmp(code, "moduleinterface") == 0) {
1518 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use the moduleinterfaces pragma.\n", input_file, line_number);
1519 } else if (Strcmp(code, "modulemethodmodifiers") == 0) {
1520 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%javamethodmodifiers.\n", input_file, line_number);
1521 } else if (Strcmp(code, "allshadowimport") == 0) {
1522 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaimports).\n", input_file, line_number);
1523 } else if (Strcmp(code, "allshadowcode") == 0) {
1524 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javacode).\n", input_file, line_number);
1525 } else if (Strcmp(code, "allshadowbase") == 0) {
1526 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javabase).\n", input_file, line_number);
1527 } else if (Strcmp(code, "allshadowinterface") == 0) {
1528 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javainterfaces).\n", input_file, line_number);
1529 } else if (Strcmp(code, "allshadowclassmodifiers") == 0) {
1530 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n", input_file, line_number);
1531 } else if (proxy_flag) {
1532 if (Strcmp(code, "shadowcode") == 0) {
1533 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javacode).\n", input_file, line_number);
1534 } else if (Strcmp(code, "shadowimport") == 0) {
1535 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaimports).\n", input_file, line_number);
1536 } else if (Strcmp(code, "shadowbase") == 0) {
1537 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javabase).\n", input_file, line_number);
1538 } else if (Strcmp(code, "shadowinterface") == 0) {
1539 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javainterfaces).\n", input_file, line_number);
1540 } else if (Strcmp(code, "shadowclassmodifiers") == 0) {
1541 Printf(stderr, "%s : Line %d. Ignored: Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n", input_file, line_number);
1543 Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
1546 Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
1551 return Language::pragmaDirective(n);
1554 /* -----------------------------------------------------------------------------
1555 * emitProxyClassDefAndCPPCasts()
1556 * ----------------------------------------------------------------------------- */
1558 void emitProxyClassDefAndCPPCasts(Node *n) {
1559 String *c_classname = SwigType_namestr(Getattr(n, "name"));
1560 String *c_baseclass = NULL;
1561 String *baseclass = NULL;
1562 String *c_baseclassname = NULL;
1563 SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
1564 bool feature_director = Swig_directorclass(n) ? true : false;
1566 // Inheritance from pure Java classes
1567 Node *attributes = NewHash();
1568 const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes);
1569 bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false;
1570 bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false;
1574 if (!purebase_replace) {
1575 List *baselist = Getattr(n, "bases");
1577 Iterator base = First(baselist);
1578 while (base.item && GetFlag(base.item, "feature:ignore")) {
1582 c_baseclassname = Getattr(base.item, "name");
1583 baseclass = Copy(getProxyName(c_baseclassname));
1585 c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
1587 /* Warn about multiple inheritance for additional base class(es) */
1589 if (GetFlag(base.item, "feature:ignore")) {
1593 String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
1594 String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
1595 Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
1596 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", proxyclassname, baseclassname);
1603 bool derived = baseclass && getProxyName(c_baseclassname);
1604 if (derived && purebase_notderived)
1605 pure_baseclass = empty_string;
1606 const String *wanted_base = baseclass ? baseclass : pure_baseclass;
1608 if (purebase_replace) {
1609 wanted_base = pure_baseclass;
1613 if (purebase_notderived)
1614 Swig_error(input_file, line_number, "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
1615 } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
1616 Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
1617 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java. "
1618 "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
1621 // Pure Java interfaces
1622 const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
1624 // Start writing the proxy class
1625 Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
1626 "\n", typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
1627 " $javaclassname", // Class name and bases
1628 (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(pure_interfaces) ? // Pure Java interfaces
1629 " implements " : "", pure_interfaces, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class
1630 typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
1633 // C++ destructor is wrapped by the delete method
1634 // Note that the method name is specified in a typemap attribute called methodname
1635 String *destruct = NewString("");
1636 const String *tm = NULL;
1637 attributes = NewHash();
1638 String *destruct_methodname = NULL;
1639 String *destruct_methodmodifiers = NULL;
1641 tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
1642 destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname");
1643 destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers");
1645 tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes);
1646 destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname");
1647 destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers");
1649 if (tm && *Char(tm)) {
1650 if (!destruct_methodname) {
1651 Swig_error(input_file, line_number,
1652 "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
1654 if (!destruct_methodmodifiers) {
1655 Swig_error(input_file, line_number,
1656 "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
1659 // Emit the finalize and delete methods
1662 if (*Char(destructor_call)) {
1663 Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL);
1666 Printv(destruct, tm, NIL);
1667 if (*Char(destructor_call))
1668 Replaceall(destruct, "$jnicall", destructor_call);
1670 Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")");
1671 if (*Char(destruct))
1672 Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " void ", destruct_methodname, "()", destructor_throws_clause, " ", destruct, "\n", NIL);
1675 /* Insert directordisconnect typemap, if this class has directors enabled */
1676 /* Also insert the swigTakeOwnership and swigReleaseOwnership methods */
1677 if (feature_director) {
1678 String *destruct_jnicall, *release_jnicall, *take_jnicall;
1680 destruct_jnicall = NewStringf("%s()", destruct_methodname);
1681 release_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, false)", imclass_name, proxy_class_name);
1682 take_jnicall = NewStringf("%s.%s_change_ownership(this, swigCPtr, true)", imclass_name, proxy_class_name);
1684 emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall);
1685 emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall);
1686 emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall);
1688 Delete(destruct_jnicall);
1689 Delete(release_jnicall);
1690 Delete(take_jnicall);
1696 // Emit extra user code
1697 Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
1700 // Substitute various strings into the above template
1701 Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
1702 Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
1704 Replaceall(proxy_class_def, "$module", module_class_name);
1705 Replaceall(proxy_class_code, "$module", module_class_name);
1707 Replaceall(proxy_class_def, "$imclassname", imclass_name);
1708 Replaceall(proxy_class_code, "$imclassname", imclass_name);
1710 // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
1712 Printv(imclass_cppcasts_code, " public final static native long SWIG$javaclassnameUpcast(long jarg1);\n", NIL);
1714 Replaceall(imclass_cppcasts_code, "$javaclassname", proxy_class_name);
1716 Printv(upcasts_code,
1717 "SWIGEXPORT jlong JNICALL Java_$jnipackage$imimclass_SWIG$imclazznameUpcast",
1718 "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
1719 " jlong baseptr = 0;\n"
1720 " (void)jenv;\n" " (void)jcls;\n" " *($cbaseclass **)&baseptr = *($cclass **)&jarg1;\n" " return baseptr;\n" "}\n", "\n", NIL);
1722 String *imimclass = makeValidJniName(imclass_name);
1723 String *imclazzname = makeValidJniName(proxy_class_name);
1724 Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
1725 Replaceall(upcasts_code, "$imclazzname", imclazzname);
1726 Replaceall(upcasts_code, "$cclass", c_classname);
1727 Replaceall(upcasts_code, "$jnipackage", jnipackage);
1728 Replaceall(upcasts_code, "$imimclass", imimclass);
1730 Delete(imclazzname);
1736 /* ----------------------------------------------------------------------
1738 * ---------------------------------------------------------------------- */
1740 virtual int classHandler(Node *n) {
1742 File *f_proxy = NULL;
1744 proxy_class_name = NewString(Getattr(n, "sym:name"));
1746 if (!addSymbol(proxy_class_name, n))
1749 if (Cmp(proxy_class_name, imclass_name) == 0) {
1750 Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
1751 SWIG_exit(EXIT_FAILURE);
1754 if (Cmp(proxy_class_name, module_class_name) == 0) {
1755 Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
1756 SWIG_exit(EXIT_FAILURE);
1759 String *filen = NewStringf("%s%s.java", SWIG_output_directory(), proxy_class_name);
1760 f_proxy = NewFile(filen, "w", SWIG_output_files());
1762 FileErrorDisplay(filen);
1763 SWIG_exit(EXIT_FAILURE);
1765 Append(filenames_list, Copy(filen));
1769 // Start writing out the proxy class file
1770 emitBanner(f_proxy);
1772 if (Len(package) > 0)
1773 Printf(f_proxy, "package %s;\n", package);
1775 Clear(proxy_class_def);
1776 Clear(proxy_class_code);
1778 destructor_call = NewString("");
1779 destructor_throws_clause = NewString("");
1780 proxy_class_constants_code = NewString("");
1783 Language::classHandler(n);
1787 emitProxyClassDefAndCPPCasts(n);
1789 Replaceall(proxy_class_def, "$module", module_class_name);
1790 Replaceall(proxy_class_code, "$module", module_class_name);
1791 Replaceall(proxy_class_constants_code, "$module", module_class_name);
1792 Replaceall(proxy_class_def, "$imclassname", imclass_name);
1793 Replaceall(proxy_class_code, "$imclassname", imclass_name);
1794 Replaceall(proxy_class_constants_code, "$imclassname", imclass_name);
1795 Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
1797 // Write out all the constants
1798 if (Len(proxy_class_constants_code) != 0)
1799 Printv(f_proxy, proxy_class_constants_code, NIL);
1801 Printf(f_proxy, "}\n");
1805 /* Output the downcast method, if necessary. Note: There's no other really
1806 good place to put this code, since Abstract Base Classes (ABCs) can and should have
1807 downcasts, making the constructorHandler() a bad place (because ABCs don't get to
1808 have constructors emitted.) */
1809 if (GetFlag(n, "feature:javadowncast")) {
1810 String *jni_imclass_name = makeValidJniName(imclass_name);
1811 String *jni_class_name = makeValidJniName(proxy_class_name);
1812 String *norm_name = SwigType_namestr(Getattr(n, "name"));
1814 Printf(imclass_class_code, " public final static native %s downcast%s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, proxy_class_name);
1816 Wrapper *dcast_wrap = NewWrapper();
1818 Printf(dcast_wrap->def, "SWIGEXPORT jobject JNICALL Java_%s%s_downcast%s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {",
1819 jnipackage, jni_imclass_name, jni_class_name);
1820 Printf(dcast_wrap->code, " Swig::Director *director = (Swig::Director *) 0;\n");
1821 Printf(dcast_wrap->code, " jobject jresult = (jobject) 0;\n");
1822 Printf(dcast_wrap->code, " %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
1823 Printf(dcast_wrap->code, " if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
1824 Printf(dcast_wrap->code, " if (director) jresult = director->swig_get_self(jenv);\n");
1825 Printf(dcast_wrap->code, " return jresult;\n");
1826 Printf(dcast_wrap->code, "}\n");
1828 Wrapper_print(dcast_wrap, f_wrappers);
1829 DelWrapper(dcast_wrap);
1832 emitDirectorExtraMethods(n);
1834 Delete(proxy_class_name);
1835 proxy_class_name = NULL;
1836 Delete(destructor_call);
1837 destructor_call = NULL;
1838 Delete(destructor_throws_clause);
1839 destructor_throws_clause = NULL;
1840 Delete(proxy_class_constants_code);
1841 proxy_class_constants_code = NULL;
1847 /* ----------------------------------------------------------------------
1848 * memberfunctionHandler()
1849 * ---------------------------------------------------------------------- */
1851 virtual int memberfunctionHandler(Node *n) {
1852 member_func_flag = true;
1853 Language::memberfunctionHandler(n);
1856 String *overloaded_name = getOverloadedName(n);
1857 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1858 Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1859 Setattr(n, "imfuncname", intermediary_function_name);
1860 proxyClassFunctionHandler(n);
1861 Delete(overloaded_name);
1863 member_func_flag = false;
1867 /* ----------------------------------------------------------------------
1868 * staticmemberfunctionHandler()
1869 * ---------------------------------------------------------------------- */
1871 virtual int staticmemberfunctionHandler(Node *n) {
1874 member_func_flag = true;
1875 Language::staticmemberfunctionHandler(n);
1878 String *overloaded_name = getOverloadedName(n);
1879 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1880 Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1881 Setattr(n, "imfuncname", intermediary_function_name);
1882 proxyClassFunctionHandler(n);
1883 Delete(overloaded_name);
1885 static_flag = false;
1886 member_func_flag = false;
1891 /* -----------------------------------------------------------------------------
1892 * proxyClassFunctionHandler()
1894 * Function called for creating a Java wrapper function around a c++ function in the
1895 * proxy class. Used for both static and non-static C++ class functions.
1896 * C++ class static functions map to Java static functions.
1897 * Two extra attributes in the Node must be available. These are "proxyfuncname" -
1898 * the name of the Java class proxy function, which in turn will call "imfuncname" -
1899 * the intermediary (JNI) function name in the intermediary class.
1900 * ----------------------------------------------------------------------------- */
1902 void proxyClassFunctionHandler(Node *n) {
1903 SwigType *t = Getattr(n, "type");
1904 ParmList *l = Getattr(n, "parms");
1905 String *intermediary_function_name = Getattr(n, "imfuncname");
1906 String *proxy_function_name = Getattr(n, "proxyfuncname");
1910 String *imcall = NewString("");
1911 String *return_type = NewString("");
1912 String *function_code = NewString("");
1913 bool setter_flag = false;
1914 String *pre_code = NewString("");
1915 String *post_code = NewString("");
1920 // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
1921 if (Getattr(n, "overload:ignore"))
1924 // Don't generate proxy method for additional explicitcall method used in directors
1925 if (GetFlag(n, "explicitcall"))
1929 if (SwigType_type(Getattr(l, "type")) == T_VOID) {
1934 /* Attach the non-standard typemaps to the parameter list */
1935 Swig_typemap_attach_parms("in", l, NULL);
1936 Swig_typemap_attach_parms("jtype", l, NULL);
1937 Swig_typemap_attach_parms("jstype", l, NULL);
1938 Swig_typemap_attach_parms("javain", l, NULL);
1940 /* Get return types */
1941 if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
1942 // 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
1943 SwigType *covariant = Getattr(n, "covariant");
1944 substituteClassname(covariant ? covariant : t, tm);
1945 Printf(return_type, "%s", tm);
1947 Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number,
1948 "Covariant return types not supported in Java. Proxy method will return %s.\n", SwigType_str(covariant, 0));
1950 Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
1953 if (wrapping_member_flag && !enum_constant_flag) {
1954 // For wrapping member variables (Javabean setter)
1955 setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0);
1958 /* Start generating the proxy function */
1959 const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1960 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1961 Printf(function_code, " %s ", methodmods);
1963 Printf(function_code, "static ");
1964 Printf(function_code, "%s %s(", return_type, proxy_function_name);
1966 Printv(imcall, imclass_name, ".$imfuncname(", NIL);
1968 Printf(imcall, "swigCPtr");
1970 String *this_type = Copy(getClassType());
1971 String *name = NewString("self");
1972 String *qualifier = Getattr(n, "qualifier");
1974 SwigType_push(this_type, qualifier);
1975 SwigType_add_pointer(this_type);
1976 Parm *this_parm = NewParm(this_type, name);
1977 Swig_typemap_attach_parms("jtype", this_parm, NULL);
1978 Swig_typemap_attach_parms("jstype", this_parm, NULL);
1980 if (prematureGarbageCollectionPreventionParameter(this_type, this_parm))
1981 Printf(imcall, ", this");
1988 emit_mark_varargs(l);
1990 int gencomma = !static_flag;
1992 /* Output each parameter */
1993 for (i = 0, p = l; p; i++) {
1995 /* Ignored varargs */
1996 if (checkAttribute(p, "varargs:ignore", "1")) {
2001 /* Ignored parameters */
2002 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2003 p = Getattr(p, "tmap:in:next");
2007 /* Ignore the 'this' argument for variable wrappers */
2008 if (!(variable_wrapper_flag && i == 0) || static_flag) {
2009 SwigType *pt = Getattr(p, "type");
2010 String *param_type = NewString("");
2012 /* Get the Java parameter type */
2013 if ((tm = Getattr(p, "tmap:jstype"))) {
2014 substituteClassname(pt, tm);
2015 Printf(param_type, "%s", tm);
2017 Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2021 Printf(imcall, ", ");
2023 String *arg = makeParameterName(n, p, i, setter_flag);
2025 // Use typemaps to transform type used in Java proxy wrapper (in proxy class) to type used in JNI function (in intermediary class)
2026 if ((tm = Getattr(p, "tmap:javain"))) {
2027 addThrows(n, "tmap:javain", p);
2028 substituteClassname(pt, tm);
2029 Replaceall(tm, "$javainput", arg);
2030 String *pre = Getattr(p, "tmap:javain:pre");
2032 substituteClassname(pt, pre);
2033 Replaceall(pre, "$javainput", arg);
2034 if (Len(pre_code) > 0)
2035 Printf(pre_code, "\n");
2036 Printv(pre_code, pre, NIL);
2038 String *post = Getattr(p, "tmap:javain:post");
2040 substituteClassname(pt, post);
2041 Replaceall(post, "$javainput", arg);
2042 if (Len(post_code) > 0)
2043 Printf(post_code, "\n");
2044 Printv(post_code, post, NIL);
2046 Printv(imcall, tm, NIL);
2048 Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2051 /* Add parameter to proxy function */
2053 Printf(function_code, ", ");
2055 Printf(function_code, "%s %s", param_type, arg);
2057 if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2058 String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2060 String *argname = Copy(pgcppname);
2061 Replaceall(argname, "$javainput", arg);
2062 Printf(imcall, ", %s", argname);
2065 Printf(imcall, ", %s", arg);
2072 p = Getattr(p, "tmap:in:next");
2075 Printf(imcall, ")");
2076 Printf(function_code, ")");
2078 // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
2079 if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
2080 addThrows(n, "tmap:javaout", n);
2081 bool is_pre_code = Len(pre_code) > 0;
2082 bool is_post_code = Len(post_code) > 0;
2083 if (is_pre_code || is_post_code) {
2084 Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
2086 Insert(tm, 0, "\n try ");
2087 Printv(tm, " finally {\n", post_code, "\n }", NIL);
2089 Insert(tm, 0, "\n ");
2092 Insert(tm, 0, pre_code);
2093 Insert(tm, 0, "\n");
2098 if (GetFlag(n, "feature:new"))
2099 Replaceall(tm, "$owner", "true");
2101 Replaceall(tm, "$owner", "false");
2102 substituteClassname(t, tm);
2104 // For director methods: generate code to selectively make a normal polymorphic call or
2105 // an explicit method call - needed to prevent infinite recursion calls in director methods.
2106 Node *explicit_n = Getattr(n, "explicitcallnode");
2108 String *ex_overloaded_name = getOverloadedName(explicit_n);
2109 String *ex_intermediary_function_name = Swig_name_member(proxy_class_name, ex_overloaded_name);
2111 String *ex_imcall = Copy(imcall);
2112 Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
2113 Replaceall(imcall, "$imfuncname", intermediary_function_name);
2115 String *excode = NewString("");
2116 if (!Cmp(return_type, "void"))
2117 Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall);
2119 Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall);
2122 Printv(imcall, excode, NIL);
2123 Delete(ex_overloaded_name);
2126 Replaceall(imcall, "$imfuncname", intermediary_function_name);
2129 Replaceall(tm, "$jnicall", imcall);
2131 Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
2134 generateThrowsClause(n, function_code);
2135 Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2136 Printv(proxy_class_code, function_code, NIL);
2140 Delete(function_code);
2141 Delete(return_type);
2145 /* ----------------------------------------------------------------------
2146 * constructorHandler()
2147 * ---------------------------------------------------------------------- */
2149 virtual int constructorHandler(Node *n) {
2151 ParmList *l = Getattr(n, "parms");
2155 String *function_code = NewString("");
2156 String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the javain typemap has code in the pre or post attributes
2157 String *helper_args = NewString("");
2158 String *pre_code = NewString("");
2159 String *post_code = NewString("");
2160 String *im_return_type = NewString("");
2161 bool feature_director = (parentNode(n) && Swig_directorclass(n));
2163 Language::constructorHandler(n);
2165 // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
2166 if (Getattr(n, "overload:ignore"))
2170 String *overloaded_name = getOverloadedName(n);
2171 String *mangled_overname = Swig_name_construct(overloaded_name);
2172 String *imcall = NewString("");
2174 const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
2175 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2177 tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
2178 Printf(im_return_type, "%s", tm);
2180 Printf(function_code, " %s %s(", methodmods, proxy_class_name);
2181 Printf(helper_code, " static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
2183 Printv(imcall, imclass_name, ".", mangled_overname, "(", NIL);
2185 /* Attach the non-standard typemaps to the parameter list */
2186 Swig_typemap_attach_parms("in", l, NULL);
2187 Swig_typemap_attach_parms("jtype", l, NULL);
2188 Swig_typemap_attach_parms("jstype", l, NULL);
2189 Swig_typemap_attach_parms("javain", l, NULL);
2191 emit_mark_varargs(l);
2195 /* Output each parameter */
2196 for (i = 0, p = l; p; i++) {
2198 /* Ignored varargs */
2199 if (checkAttribute(p, "varargs:ignore", "1")) {
2204 /* Ignored parameters */
2205 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2206 p = Getattr(p, "tmap:in:next");
2210 SwigType *pt = Getattr(p, "type");
2211 String *param_type = NewString("");
2213 /* Get the Java parameter type */
2214 if ((tm = Getattr(p, "tmap:jstype"))) {
2215 substituteClassname(pt, tm);
2216 Printf(param_type, "%s", tm);
2218 Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2222 Printf(imcall, ", ");
2224 String *arg = makeParameterName(n, p, i, false);
2226 // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
2227 if ((tm = Getattr(p, "tmap:javain"))) {
2228 addThrows(n, "tmap:javain", p);
2229 substituteClassname(pt, tm);
2230 Replaceall(tm, "$javainput", arg);
2231 String *pre = Getattr(p, "tmap:javain:pre");
2233 substituteClassname(pt, pre);
2234 Replaceall(pre, "$javainput", arg);
2235 if (Len(pre_code) > 0)
2236 Printf(pre_code, "\n");
2237 Printv(pre_code, pre, NIL);
2239 String *post = Getattr(p, "tmap:javain:post");
2241 substituteClassname(pt, post);
2242 Replaceall(post, "$javainput", arg);
2243 if (Len(post_code) > 0)
2244 Printf(post_code, "\n");
2245 Printv(post_code, post, NIL);
2247 Printv(imcall, tm, NIL);
2249 Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2252 /* Add parameter to proxy function */
2254 Printf(function_code, ", ");
2255 Printf(helper_code, ", ");
2256 Printf(helper_args, ", ");
2258 Printf(function_code, "%s %s", param_type, arg);
2259 Printf(helper_code, "%s %s", param_type, arg);
2260 Printf(helper_args, "%s", arg);
2263 if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2264 String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2266 String *argname = Copy(pgcppname);
2267 Replaceall(argname, "$javainput", arg);
2268 Printf(imcall, ", %s", argname);
2271 Printf(imcall, ", %s", arg);
2277 p = Getattr(p, "tmap:in:next");
2280 Printf(imcall, ")");
2282 Printf(function_code, ")");
2283 Printf(helper_code, ")");
2284 generateThrowsClause(n, function_code);
2286 /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
2287 Hash *attributes = NewHash();
2288 String *construct_tm = Copy(typemapLookup(n, "javaconstruct", Getattr(n, "name"),
2289 WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
2291 if (!feature_director) {
2292 Replaceall(construct_tm, "$directorconnect", "");
2294 String *connect_attr = Getattr(attributes, "tmap:javaconstruct:directorconnect");
2297 Replaceall(construct_tm, "$directorconnect", connect_attr);
2299 Swig_warning(WARN_JAVA_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"javaconstruct\" typemap.\n",
2300 Getattr(n, "name"));
2301 Replaceall(construct_tm, "$directorconnect", "");
2305 Printv(function_code, " ", construct_tm, "\n", NIL);
2308 bool is_pre_code = Len(pre_code) > 0;
2309 bool is_post_code = Len(post_code) > 0;
2310 if (is_pre_code || is_post_code) {
2311 generateThrowsClause(n, helper_code);
2312 Printf(helper_code, " {\n");
2314 Printv(helper_code, pre_code, "\n", NIL);
2317 Printf(helper_code, " try {\n");
2318 Printv(helper_code, " return ", imcall, ";\n", NIL);
2319 Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
2321 Printv(helper_code, " return ", imcall, ";", NIL);
2323 Printf(helper_code, "\n }\n");
2324 String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
2325 Printv(proxy_class_code, helper_code, "\n", NIL);
2326 Replaceall(function_code, "$imcall", helper_name);
2327 Delete(helper_name);
2329 Replaceall(function_code, "$imcall", imcall);
2332 Printv(proxy_class_code, function_code, "\n", NIL);
2334 Delete(helper_args);
2335 Delete(im_return_type);
2338 Delete(construct_tm);
2340 Delete(overloaded_name);
2347 /* ----------------------------------------------------------------------
2348 * destructorHandler()
2349 * ---------------------------------------------------------------------- */
2351 virtual int destructorHandler(Node *n) {
2352 Language::destructorHandler(n);
2353 String *symname = Getattr(n, "sym:name");
2356 Printv(destructor_call, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
2357 generateThrowsClause(n, destructor_throws_clause);
2362 /* ----------------------------------------------------------------------
2363 * membervariableHandler()
2364 * ---------------------------------------------------------------------- */
2366 virtual int membervariableHandler(Node *n) {
2367 variable_name = Getattr(n, "sym:name");
2368 wrapping_member_flag = true;
2369 variable_wrapper_flag = true;
2370 Language::membervariableHandler(n);
2371 wrapping_member_flag = false;
2372 variable_wrapper_flag = false;
2376 /* ----------------------------------------------------------------------
2377 * staticmembervariableHandler()
2378 * ---------------------------------------------------------------------- */
2380 virtual int staticmembervariableHandler(Node *n) {
2381 variable_name = Getattr(n, "sym:name");
2382 wrapping_member_flag = true;
2384 Language::staticmembervariableHandler(n);
2385 wrapping_member_flag = false;
2386 static_flag = false;
2390 /* ----------------------------------------------------------------------
2391 * memberconstantHandler()
2392 * ---------------------------------------------------------------------- */
2394 virtual int memberconstantHandler(Node *n) {
2395 variable_name = Getattr(n, "sym:name");
2396 wrapping_member_flag = true;
2397 Language::memberconstantHandler(n);
2398 wrapping_member_flag = false;
2402 /* -----------------------------------------------------------------------------
2403 * getOverloadedName()
2404 * ----------------------------------------------------------------------------- */
2406 String *getOverloadedName(Node *n) {
2408 /* Although JNI functions are designed to handle overloaded Java functions,
2409 * a Java long is used for all classes in the SWIG intermediary class.
2410 * The intermediary class methods are thus mangled when overloaded to give
2412 String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
2414 if (Getattr(n, "sym:overloaded")) {
2415 Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
2418 return overloaded_name;
2421 /* -----------------------------------------------------------------------------
2422 * moduleClassFunctionHandler()
2423 * ----------------------------------------------------------------------------- */
2425 void moduleClassFunctionHandler(Node *n) {
2426 SwigType *t = Getattr(n, "type");
2427 ParmList *l = Getattr(n, "parms");
2431 String *imcall = NewString("");
2432 String *return_type = NewString("");
2433 String *function_code = NewString("");
2434 int num_arguments = 0;
2435 int num_required = 0;
2436 String *overloaded_name = getOverloadedName(n);
2437 String *func_name = NULL;
2438 bool setter_flag = false;
2439 String *pre_code = NewString("");
2440 String *post_code = NewString("");
2443 if (SwigType_type(Getattr(l, "type")) == T_VOID) {
2448 /* Attach the non-standard typemaps to the parameter list */
2449 Swig_typemap_attach_parms("jstype", l, NULL);
2450 Swig_typemap_attach_parms("javain", l, NULL);
2452 /* Get return types */
2453 if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
2454 substituteClassname(t, tm);
2455 Printf(return_type, "%s", tm);
2457 Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
2460 /* Change function name for global variables */
2461 if (proxy_flag && global_variable_flag) {
2462 // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
2463 func_name = NewString("");
2464 setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(variable_name)) == 0);
2466 Printf(func_name, "set");
2468 Printf(func_name, "get");
2469 Putc(toupper((int) *Char(variable_name)), func_name);
2470 Printf(func_name, "%s", Char(variable_name) + 1);
2472 func_name = Copy(Getattr(n, "sym:name"));
2475 /* Start generating the function */
2476 const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
2477 methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2478 Printf(function_code, " %s static %s %s(", methodmods, return_type, func_name);
2479 Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
2481 /* Get number of required and total arguments */
2482 num_arguments = emit_num_arguments(l);
2483 num_required = emit_num_required(l);
2485 bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
2488 /* Output each parameter */
2489 for (i = 0, p = l; i < num_arguments; i++) {
2491 /* Ignored parameters */
2492 while (checkAttribute(p, "tmap:in:numinputs", "0")) {
2493 p = Getattr(p, "tmap:in:next");
2496 SwigType *pt = Getattr(p, "type");
2497 String *param_type = NewString("");
2499 /* Get the Java parameter type */
2500 if ((tm = Getattr(p, "tmap:jstype"))) {
2501 substituteClassname(pt, tm);
2502 Printf(param_type, "%s", tm);
2504 Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2508 Printf(imcall, ", ");
2510 String *arg = makeParameterName(n, p, i, global_or_member_variable);
2512 // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
2513 if ((tm = Getattr(p, "tmap:javain"))) {
2514 addThrows(n, "tmap:javain", p);
2515 substituteClassname(pt, tm);
2516 Replaceall(tm, "$javainput", arg);
2517 String *pre = Getattr(p, "tmap:javain:pre");
2519 substituteClassname(pt, pre);
2520 Replaceall(pre, "$javainput", arg);
2521 if (Len(pre_code) > 0)
2522 Printf(pre_code, "\n");
2523 Printv(pre_code, pre, NIL);
2525 String *post = Getattr(p, "tmap:javain:post");
2527 substituteClassname(pt, post);
2528 Replaceall(post, "$javainput", arg);
2529 if (Len(post_code) > 0)
2530 Printf(post_code, "\n");
2531 Printv(post_code, post, NIL);
2533 Printv(imcall, tm, NIL);
2535 Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2538 /* Add parameter to module class function */
2540 Printf(function_code, ", ");
2542 Printf(function_code, "%s %s", param_type, arg);
2544 if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2545 String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2547 String *argname = Copy(pgcppname);
2548 Replaceall(argname, "$javainput", arg);
2549 Printf(imcall, ", %s", argname);
2552 Printf(imcall, ", %s", arg);
2556 p = Getattr(p, "tmap:in:next");
2561 Printf(imcall, ")");
2562 Printf(function_code, ")");
2564 // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in module class)
2565 if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
2566 addThrows(n, "tmap:javaout", n);
2567 bool is_pre_code = Len(pre_code) > 0;
2568 bool is_post_code = Len(post_code) > 0;
2569 if (is_pre_code || is_post_code) {
2570 Replaceall(tm, "\n ", "\n "); // add extra indentation to code in typemap
2572 Insert(tm, 0, "\n try ");
2573 Printv(tm, " finally {\n", post_code, "\n }", NIL);
2575 Insert(tm, 0, "\n ");
2578 Insert(tm, 0, pre_code);
2579 Insert(tm, 0, "\n");
2584 if (GetFlag(n, "feature:new"))
2585 Replaceall(tm, "$owner", "true");
2587 Replaceall(tm, "$owner", "false");
2588 substituteClassname(t, tm);
2589 Replaceall(tm, "$jnicall", imcall);
2591 Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
2594 generateThrowsClause(n, function_code);
2595 Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2596 Printv(module_class_code, function_code, NIL);
2600 Delete(function_code);
2601 Delete(return_type);
2606 /*----------------------------------------------------------------------
2607 * replaceSpecialVariables()
2608 *--------------------------------------------------------------------*/
2610 virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
2612 SwigType *type = Getattr(parm, "type");
2613 substituteClassname(type, tm);
2616 /*----------------------------------------------------------------------
2617 * decodeEnumFeature()
2618 * Decode the possible enum features, which are one of:
2620 * %javaenum(typeunsafe) - default
2621 * %javaenum(typesafe)
2623 *--------------------------------------------------------------------*/
2625 EnumFeature decodeEnumFeature(Node *n) {
2626 EnumFeature enum_feature = TypeunsafeEnum;
2627 String *feature = Getattr(n, "feature:java:enum");
2629 if (Cmp(feature, "simple") == 0)
2630 enum_feature = SimpleEnum;
2631 else if (Cmp(feature, "typesafe") == 0)
2632 enum_feature = TypesafeEnum;
2633 else if (Cmp(feature, "proper") == 0)
2634 enum_feature = ProperEnum;
2636 return enum_feature;
2639 /* -----------------------------------------------------------------------
2641 * This method will return a string with an enum value to use in Java generated
2642 * code. If the %javaconst feature is not used, the string will contain the intermediary
2643 * class call to obtain the enum value. The intermediary class and JNI methods to obtain
2644 * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
2645 * is one and hopefully it will compile as Java code - e.g. 20 as in: enum E{e=20};
2646 * The %javaconstvalue feature overrides all other ways to generate the constant value.
2647 * The caller must delete memory allocated for the returned string.
2648 * ------------------------------------------------------------------------ */
2650 String *enumValue(Node *n) {
2651 String *symname = Getattr(n, "sym:name");
2653 // Check for the %javaconstvalue feature
2654 String *value = Getattr(n, "feature:java:constvalue");
2657 // The %javaconst feature determines how the constant value is obtained
2658 int const_feature_flag = GetFlag(n, "feature:java:const");
2660 if (const_feature_flag) {
2661 // Use the C syntax to make a true Java constant and hope that it compiles as Java code
2662 value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
2664 // Get the enumvalue from a JNI call
2665 if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
2666 // Strange hack to change the name
2667 Setattr(n, "name", Getattr(n, "value")); /* for wrapping of enums in a namespace when emit_action is used */
2669 value = NewStringf("%s.%s()", imclass_name, Swig_name_get(symname));
2671 memberconstantHandler(n);
2672 value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname)));
2679 /* -----------------------------------------------------------------------------
2682 * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.'
2683 * ----------------------------------------------------------------------------- */
2685 String *getEnumName(SwigType *t, bool jnidescriptor) {
2686 Node *enum_name = NULL;
2687 Node *n = enumLookup(t);
2689 String *symname = Getattr(n, "sym:name");
2691 // Add in class scope when referencing enum if not a global enum
2692 String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
2693 String *proxyname = 0;
2694 if (scopename_prefix) {
2695 proxyname = getProxyName(scopename_prefix);
2698 const char *class_separator = jnidescriptor ? "$" : ".";
2699 enum_name = NewStringf("%s%s%s", proxyname, class_separator, symname);
2701 enum_name = NewStringf("%s", symname);
2703 Delete(scopename_prefix);
2710 /* -----------------------------------------------------------------------------
2711 * substituteClassname()
2713 * Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions
2714 * that SWIG knows about. Also substitutes enums with enum name.
2715 * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
2716 * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
2718 * pt - parameter type
2719 * tm - typemap contents that might contain the special variable to be replaced
2720 * jnidescriptor - if set, inner class names are separated with '$' otherwise a '.'
2722 * tm - typemap contents complete with the special variable substitution
2724 * substitution_performed - flag indicating if a substitution was performed
2725 * ----------------------------------------------------------------------------- */
2727 bool substituteClassname(SwigType *pt, String *tm, bool jnidescriptor = false) {
2728 bool substitution_performed = false;
2729 SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
2730 SwigType *strippedtype = SwigType_strip_qualifiers(type);
2732 if (Strstr(tm, "$javaclassname")) {
2733 SwigType *classnametype = Copy(strippedtype);
2734 substituteClassnameSpecialVariable(classnametype, tm, "$javaclassname", jnidescriptor);
2735 substitution_performed = true;
2736 Delete(classnametype);
2738 if (Strstr(tm, "$*javaclassname")) {
2739 SwigType *classnametype = Copy(strippedtype);
2740 Delete(SwigType_pop(classnametype));
2741 substituteClassnameSpecialVariable(classnametype, tm, "$*javaclassname", jnidescriptor);
2742 substitution_performed = true;
2743 Delete(classnametype);
2745 if (Strstr(tm, "$&javaclassname")) {
2746 SwigType *classnametype = Copy(strippedtype);
2747 SwigType_add_pointer(classnametype);
2748 substituteClassnameSpecialVariable(classnametype, tm, "$&javaclassname", jnidescriptor);
2749 substitution_performed = true;
2750 Delete(classnametype);
2753 Delete(strippedtype);
2756 return substitution_performed;
2759 /* -----------------------------------------------------------------------------
2760 * substituteClassnameSpecialVariable()
2761 * ----------------------------------------------------------------------------- */
2763 void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) {
2764 if (SwigType_isenum(classnametype)) {
2765 String *enumname = getEnumName(classnametype, jnidescriptor);
2767 Replaceall(tm, classnamespecialvariable, enumname);
2769 Replaceall(tm, classnamespecialvariable, NewStringf("int"));
2771 String *classname = getProxyName(classnametype);
2773 Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too
2774 } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
2775 String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
2776 Replaceall(tm, classnamespecialvariable, descriptor);
2778 // Add to hash table so that the type wrapper classes can be created later
2779 Setattr(swig_types_hash, descriptor, classnametype);
2785 /* -----------------------------------------------------------------------------
2786 * makeParameterName()
2790 * p - parameter node
2791 * arg_num - parameter argument number
2792 * setter - set this flag when wrapping variables
2794 * arg - a unique parameter name
2795 * ----------------------------------------------------------------------------- */
2797 String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
2800 String *pn = Getattr(p, "name");
2802 // Use C parameter name unless it is a duplicate or an empty parameter name
2804 ParmList *plist = Getattr(n, "parms");
2806 if ((Cmp(pn, Getattr(plist, "name")) == 0))
2808 plist = nextSibling(plist);
2810 String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
2811 arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
2813 if (setter && Cmp(arg, "self") != 0) {
2814 // Note that for setters the parameter name is always set but sometimes includes C++
2815 // scope resolution, so we need to strip off the scope resolution to make a valid name.
2817 arg = NewString("value"); //Swig_scopename_last(pn);
2823 /* -----------------------------------------------------------------------------
2824 * emitTypeWrapperClass()
2825 * ----------------------------------------------------------------------------- */
2827 void emitTypeWrapperClass(String *classname, SwigType *type) {
2828 Node *n = NewHash();
2829 Setfile(n, input_file);
2830 Setline(n, line_number);
2832 String *swigtype = NewString("");
2833 String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname);
2834 File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
2836 FileErrorDisplay(filen);
2837 SWIG_exit(EXIT_FAILURE);
2839 Append(filenames_list, Copy(filen));
2843 // Start writing out the type wrapper class file
2844 emitBanner(f_swigtype);
2846 if (Len(package) > 0)
2847 Printf(f_swigtype, "package %s;\n", package);
2849 // Pure Java baseclass and interfaces
2850 const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE);
2851 const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE);
2854 Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE), // Import statements
2855 "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
2856 " $javaclassname", // Class name and bases
2857 *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
2858 " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
2859 typemapLookup(n, "javacode", type, WARN_NONE), // extra Java code
2862 Replaceall(swigtype, "$javaclassname", classname);
2863 Replaceall(swigtype, "$module", module_class_name);
2864 Replaceall(swigtype, "$imclassname", imclass_name);
2865 Printv(f_swigtype, swigtype, NIL);
2872 /* -----------------------------------------------------------------------------
2874 * n - for input only and must contain info for Getfile(n) and Getline(n) to work
2875 * tmap_method - typemap method name
2876 * type - typemap type to lookup
2877 * warning - warning number to issue if no typemaps found
2878 * typemap_attributes - the typemap attributes are attached to this node and will
2879 * also be used for temporary storage if non null
2880 * return is never NULL, unlike Swig_typemap_lookup()
2881 * ----------------------------------------------------------------------------- */
2883 const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
2884 Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
2885 Setattr(node, "type", type);
2886 Setfile(node, Getfile(n));
2887 Setline(node, Getline(n));
2888 const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
2891 if (warning != WARN_NONE)
2892 Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
2894 if (!typemap_attributes)
2899 /* -----------------------------------------------------------------------------
2902 * Adds exception classes to a throws list. The throws list is the list of classes
2903 * that will form the Java throws clause. Mainly for checked exceptions.
2904 * ----------------------------------------------------------------------------- */
2906 void addThrows(Node *n, const String *attribute, Node *parameter) {
2907 // Get the comma separated exception classes for the throws clause - held in typemap/feature's "throws" attribute
2908 String *throws_attribute = NewStringf("%s:throws", attribute);
2909 String *throws = Getattr(parameter, throws_attribute);
2911 if (throws && Len(throws) > 0) {
2912 String *throws_list = Getattr(n, "java:throwslist");
2914 throws_list = NewList();
2915 Setattr(n, "java:throwslist", throws_list);
2917 // Put the exception classes in the throws clause into a temporary List
2918 List *temp_classes_list = Split(throws, ',', INT_MAX);
2920 // Add the exception classes to the node throws list, but don't duplicate if already in list
2921 if (temp_classes_list && Len(temp_classes_list) > 0) {
2922 for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) {
2923 String *exception_class = NewString(cls.item);
2924 Replaceall(exception_class, " ", ""); // remove spaces
2925 Replaceall(exception_class, "\t", ""); // remove tabs
2926 if (Len(exception_class) > 0) {
2927 // $javaclassname substitution
2928 SwigType *pt = Getattr(parameter, "type");
2929 substituteClassname(pt, exception_class);
2931 // Don't duplicate the Java exception class in the throws clause
2932 bool found_flag = false;
2933 for (Iterator item = First(throws_list); item.item; item = Next(item)) {
2934 if (Strcmp(item.item, exception_class) == 0)
2938 Append(throws_list, exception_class);
2940 Delete(exception_class);
2943 Delete(temp_classes_list);
2945 Delete(throws_attribute);
2948 /* -----------------------------------------------------------------------------
2949 * generateThrowsClause()
2951 * Generates throws clause for checked exception
2952 * ----------------------------------------------------------------------------- */
2954 void generateThrowsClause(Node *n, String *code) {
2955 // Add the throws clause into code
2956 List *throws_list = Getattr(n, "java:throwslist");
2958 Iterator cls = First(throws_list);
2959 Printf(code, " throws %s", cls.item);
2960 while ((cls = Next(cls)).item)
2961 Printf(code, ", %s", cls.item);
2965 /* -----------------------------------------------------------------------------
2966 * prematureGarbageCollectionPreventionParameter()
2968 * Get the proxy class name for use in an additional generated parameter. The
2969 * additional parameter is added to a native method call purely to prevent
2970 * premature garbage collection of proxy classes which pass their C++ class pointer
2971 * in a Java long to the JNI layer.
2972 * ----------------------------------------------------------------------------- */
2974 String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) {
2975 String *proxyClassName = 0;
2976 String *jtype = NewString(Getattr(p, "tmap:jtype"));
2979 String *stripped_jtype = Swig_strip_c_comments(jtype);
2980 if (stripped_jtype) {
2982 jtype = stripped_jtype;
2985 // Remove whitespace
2986 Replaceall(jtype, " ", "");
2987 Replaceall(jtype, "\t", "");
2989 if (Cmp(jtype, "long") == 0) {
2991 if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) {
2992 Node *n = classLookup(t);
2994 // Found a struct/class parameter passed by value, reference, pointer, or pointer reference
2995 proxyClassName = Getattr(n, "sym:name");
2997 // Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types
2998 String *jstype = NewString(Getattr(p, "tmap:jstype"));
3000 Hash *classes = getClassHash();
3003 String *stripped_jstype = Swig_strip_c_comments(jstype);
3004 if (stripped_jstype) {
3006 jstype = stripped_jstype;
3008 // Remove whitespace
3009 Replaceall(jstype, " ", "");
3010 Replaceall(jstype, "\t", "");
3013 for (ki = First(classes); ki.key; ki = Next(ki)) {
3014 Node *cls = ki.item;
3015 if (cls && !Getattr(cls, "feature:ignore")) {
3016 String *symname = Getattr(cls, "sym:name");
3017 if (symname && Strcmp(symname, jstype) == 0) {
3018 proxyClassName = symname;
3030 return proxyClassName;
3033 /*----------------------------------------------------------------------
3034 * Start of director methods
3035 *--------------------------------------------------------------------*/
3037 /*----------------------------------------------------------------------
3038 * getUpcallJNIMethod()
3039 *--------------------------------------------------------------------*/
3041 String *getUpcallJNIMethod(String *descrip) {
3045 } upcall_methods[] = {
3047 'B', "CallStaticByteMethod"}, {
3048 'C', "CallStaticCharMethod"}, {
3049 'D', "CallStaticDoubleMethod"}, {
3050 'F', "CallStaticFloatMethod"}, {
3051 'I', "CallStaticIntMethod"}, {
3052 'J', "CallStaticLongMethod"}, {
3053 'L', "CallStaticObjectMethod"}, {
3054 'S', "CallStaticShortMethod"}, {
3055 'V', "CallStaticVoidMethod"}, {
3056 'Z', "CallStaticBooleanMethod"}, {
3057 '[', "CallStaticObjectMethod"}
3063 code = *Char(descrip);
3064 for (i = 0; i < (int) (sizeof(upcall_methods) / sizeof(upcall_methods[0])); ++i)
3065 if (code == upcall_methods[i].code)
3066 return NewString(upcall_methods[i].method);
3070 /*----------------------------------------------------------------------
3071 * emitDirectorUpcalls()
3072 *--------------------------------------------------------------------*/
3074 void emitDirectorUpcalls() {
3076 Wrapper *w = NewWrapper();
3077 String *jni_imclass_name = makeValidJniName(imclass_name);
3078 String *swig_module_init = NewString("swig_module_init");
3079 String *swig_module_init_jni = makeValidJniName(swig_module_init);
3080 String *dmethod_data = NewString("");
3082 Iterator udata_iter;
3084 udata_iter = First(dmethods_seq);
3085 while (udata_iter.item) {
3086 UpcallData *udata = udata_iter.item;
3087 Printf(dmethod_data, " { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
3090 udata_iter = Next(udata_iter);
3092 if (udata_iter.item)
3093 Putc(',', dmethod_data);
3094 Putc('\n', dmethod_data);
3097 Printf(f_runtime, "namespace Swig {\n");
3098 Printf(f_runtime, " static jclass jclass_%s = NULL;\n", imclass_name);
3099 Printf(f_runtime, " static jmethodID director_methids[%d];\n", n_methods);
3100 Printf(f_runtime, "}\n");
3102 Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni);
3103 Printf(w->code, "static struct {\n");
3104 Printf(w->code, " const char *method;\n");
3105 Printf(w->code, " const char *signature;\n");
3106 Printf(w->code, "} methods[%d] = {\n", n_methods);
3107 Printv(w->code, dmethod_data, NIL);
3108 Printf(w->code, "};\n");
3110 Wrapper_add_local(w, "i", "int i");
3112 Printf(w->code, "Swig::jclass_%s = (jclass) jenv->NewGlobalRef(jcls);\n", imclass_name);
3113 Printf(w->code, "if (!Swig::jclass_%s) return;\n", imclass_name);
3114 Printf(w->code, "for (i = 0; i < (int) (sizeof(methods)/sizeof(methods[0])); ++i) {\n");
3115 Printf(w->code, " Swig::director_methids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n");
3116 Printf(w->code, " if (!Swig::director_methids[i]) return;\n");
3117 Printf(w->code, "}\n");
3119 Printf(w->code, "}\n");
3121 Wrapper_print(w, f_wrappers);
3122 Delete(dmethod_data);
3123 Delete(swig_module_init_jni);
3124 Delete(swig_module_init);
3125 Delete(jni_imclass_name);
3130 /*----------------------------------------------------------------------
3131 * emitDirectorExtraMethods()
3133 * This is where the $javaclassname_director_connect is
3135 *--------------------------------------------------------------------*/
3136 void emitDirectorExtraMethods(Node *n) {
3137 if (!Swig_directorclass(n))
3140 // Output the director connect method:
3141 String *jni_imclass_name = makeValidJniName(imclass_name);
3142 String *norm_name = SwigType_namestr(Getattr(n, "name"));
3143 String *swig_director_connect = NewStringf("%s_director_connect", proxy_class_name);
3144 String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
3145 String *sym_name = Getattr(n, "sym:name");
3148 Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean mem_own, boolean weak_global);\n",
3149 swig_director_connect, proxy_class_name);
3151 code_wrap = NewWrapper();
3152 Printf(code_wrap->def,
3153 "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jswig_mem_own, "
3154 "jboolean jweak_global) {\n", jnipackage, jni_imclass_name, swig_director_connect_jni);
3155 Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
3156 Printf(code_wrap->code, " (void)jcls;\n");
3157 Printf(code_wrap->code, " SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
3158 Printf(code_wrap->code, " if (director) {\n");
3159 Printf(code_wrap->code, " director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
3160 "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n");
3161 Printf(code_wrap->code, " }\n");
3162 Printf(code_wrap->code, "}\n");
3164 Wrapper_print(code_wrap, f_wrappers);
3165 DelWrapper(code_wrap);
3167 Delete(swig_director_connect_jni);
3168 Delete(swig_director_connect);
3170 // Output the swigReleaseOwnership, swigTakeOwnership methods:
3171 String *changeown_method_name = NewStringf("%s_change_ownership", proxy_class_name);
3172 String *changeown_jnimethod_name = makeValidJniName(changeown_method_name);
3174 Printf(imclass_class_code, " public final static native void %s(%s obj, long cptr, boolean take_or_release);\n", changeown_method_name, proxy_class_name);
3176 code_wrap = NewWrapper();
3177 Printf(code_wrap->def,
3178 "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n",
3179 jnipackage, jni_imclass_name, changeown_jnimethod_name);
3180 Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
3181 Printf(code_wrap->code, " SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
3182 Printf(code_wrap->code, " (void)jcls;\n");
3183 Printf(code_wrap->code, " if (director) {\n");
3184 Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
3185 Printf(code_wrap->code, " }\n");
3186 Printf(code_wrap->code, "}\n");
3188 Wrapper_print(code_wrap, f_wrappers);
3189 DelWrapper(code_wrap);
3191 Delete(changeown_method_name);
3192 Delete(changeown_jnimethod_name);
3194 Delete(jni_imclass_name);
3197 /*----------------------------------------------------------------------
3200 * Output a code typemap that uses $methodname and $jnicall, as used
3201 * in the directordisconnect, director_release and director_take
3203 *--------------------------------------------------------------------*/
3205 void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) {
3206 const String *tm = NULL;
3207 Node *tmattrs = NewHash();
3208 String *lookup_tmname = NewString(typemap);
3209 String *method_attr_name;
3210 String *method_attr;
3213 Append(lookup_tmname, "_derived");
3216 tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs);
3217 method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname);
3218 method_attr = Getattr(tmattrs, method_attr_name);
3222 String *codebody = Copy(tm);
3223 Replaceall(codebody, "$methodname", method_attr);
3224 Replaceall(codebody, "$jnicall", jnicall);
3225 Append(proxy_class_def, codebody);
3228 Swig_error(input_file, line_number, "No %s method name attribute for %s\n", lookup_tmname, proxy_class_name);
3231 Swig_error(input_file, line_number, "No %s typemap for %s\n", lookup_tmname, proxy_class_name);
3235 Delete(lookup_tmname);
3236 // Delete(method_attr);
3239 /* ---------------------------------------------------------------
3240 * Canonicalize the JNI field descriptor
3242 * Replace the $javapackage and $javaclassname family of special
3243 * variables with the desired package and Java proxy name as
3244 * required in the JNI field descriptors.
3246 * !!SFM!! If $packagepath occurs in the field descriptor, but
3247 * package_path isn't set (length == 0), then strip it and the
3248 * optional trailing '/' from the resulting name.
3250 * --------------------------------------------------------------- */
3252 String *canonicalizeJNIDescriptor(String *descriptor_in, Parm *p) {
3253 String *pkg_path = Swig_typemap_lookup("javapackage", p, "", 0);
3254 SwigType *type = Getattr(p, "type");
3256 if (pkg_path && Len(pkg_path) != 0) {
3257 Replaceall(pkg_path, ".", "/");
3259 pkg_path = package_path;
3261 String *descriptor_out = Copy(descriptor_in);
3263 if (Len(pkg_path) > 0) {
3264 Replaceall(descriptor_out, "$packagepath", pkg_path);
3266 Replaceall(descriptor_out, "$packagepath/", empty_string);
3267 Replaceall(descriptor_out, "$packagepath", empty_string);
3270 substituteClassname(type, descriptor_out, true);
3272 if (pkg_path != package_path)
3275 return descriptor_out;
3278 /* ---------------------------------------------------------------
3279 * classDirectorMethod()
3281 * Emit a virtual director method to pass a method call on to the
3282 * underlying Java object.
3284 * --------------------------------------------------------------- */
3286 int classDirectorMethod(Node *n, Node *parent, String *super) {
3287 String *empty_str = NewString("");
3288 String *classname = Getattr(parent, "sym:name");
3289 String *c_classname = Getattr(parent, "name");
3290 String *name = Getattr(n, "name");
3291 String *symname = Getattr(n, "sym:name");
3292 SwigType *type = Getattr(n, "type");
3293 SwigType *returntype = Getattr(n, "returntype");
3294 String *overloaded_name = getOverloadedName(n);
3295 String *storage = Getattr(n, "storage");
3296 String *value = Getattr(n, "value");
3297 String *decl = Getattr(n, "decl");
3298 String *declaration = NewString("");
3302 Wrapper *w = NewWrapper();
3303 ParmList *l = Getattr(n, "parms");
3304 bool is_void = !(Cmp(returntype, "void"));
3305 String *qualified_return = NewString("");
3306 bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
3307 int status = SWIG_OK;
3308 bool output_director = true;
3309 String *dirclassname = directorClassName(parent);
3310 String *qualified_name = NewStringf("%s::%s", dirclassname, name);
3311 String *jnidesc = NewString("");
3312 String *classdesc = NewString("");
3313 String *jniret_desc = NewString("");
3314 String *classret_desc = NewString("");
3315 SwigType *c_ret_type = NULL;
3316 String *jupcall_args = NewString("swigjobj");
3317 String *imclass_dmethod;
3318 String *callback_def = NewString("");
3319 String *callback_code = NewString("");
3320 String *imcall_args = NewString("");
3322 int classmeth_off = curr_class_dmethod - first_class_dmethod;
3323 bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
3325 // Kludge Alert: functionWrapper sets sym:overload properly, but it
3326 // isn't at this point, so we have to manufacture it ourselves. At least
3327 // we're consistent with the sym:overload name in functionWrapper. (?? when
3328 // does the overloaded method name get set?)
3330 imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(classname, overloaded_name));
3334 qualified_return = SwigType_rcaststr(returntype, "c_result");
3336 if (!is_void && (!ignored_method || pure_virtual)) {
3337 if (!SwigType_isclass(returntype)) {
3338 if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
3339 String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
3340 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
3341 Delete(construct_result);
3343 String *base_typename = SwigType_base(returntype);
3344 String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
3345 Symtab *symtab = Getattr(n, "sym:symtab");
3346 Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
3348 if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstract"))) {
3349 /* initialize pointers to something sane. Same for abstract
3350 classes when a reference is returned. */
3351 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
3353 /* If returning a reference, initialize the pointer to a sane
3354 default - if a Java exception occurs, then the pointer returns
3355 something other than a NULL-initialized reference. */
3356 String *non_ref_type = Copy(returntype);
3358 /* Remove reference and const qualifiers */
3359 Replaceall(non_ref_type, "r.", "");
3360 Replaceall(non_ref_type, "q(const).", "");
3361 Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
3362 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
3364 Delete(non_ref_type);
3367 Delete(base_typename);
3368 Delete(resolved_typename);
3373 vt = cplus_value_type(returntype);
3375 Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
3377 Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
3383 /* Create the intermediate class wrapper */
3384 Parm *tp = NewParmFromNode(returntype, empty_str, n);
3386 tm = Swig_typemap_lookup("jtype", tp, "", 0);
3388 Printf(callback_def, " public static %s %s(%s self", tm, imclass_dmethod, classname);
3390 Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0));
3393 String *cdesc = NULL;
3394 SwigType *covariant = Getattr(n, "covariant");
3395 SwigType *adjustedreturntype = covariant ? covariant : returntype;
3396 Parm *adjustedreturntypeparm = NewParmFromNode(adjustedreturntype, empty_str, n);
3398 if ((tm = Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0))
3399 && (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) {
3401 // Note that in the case of polymorphic (covariant) return types, the
3402 // method's return type is changed to be the base of the C++ return
3404 String *jnidesc_canon = canonicalizeJNIDescriptor(cdesc, adjustedreturntypeparm);
3405 Append(classret_desc, jnidesc_canon);
3406 Delete(jnidesc_canon);
3408 Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3409 SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3410 output_director = false;
3413 /* Get the JNI field descriptor for this return type, add the JNI field descriptor
3416 Parm *retpm = NewParmFromNode(returntype, empty_str, n);
3418 if ((c_ret_type = Swig_typemap_lookup("jni", retpm, "", 0))) {
3419 Parm *tp = NewParmFromNode(c_ret_type, empty_str, n);
3421 if (!is_void && !ignored_method) {
3422 String *jretval_decl = NewStringf("%s jresult", c_ret_type);
3423 Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
3424 Delete(jretval_decl);
3427 String *jdesc = NULL;
3428 if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
3429 && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
3431 // Objects marshalled passing a Java class across JNI boundary use jobject - the nouse flag indicates this
3432 // We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
3433 if (GetFlag(tp, "tmap:directorin:nouse"))
3435 String *jnidesc_canon = canonicalizeJNIDescriptor(jdesc, tp);
3436 Append(jniret_desc, jnidesc_canon);
3437 Delete(jnidesc_canon);
3439 Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
3440 "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3441 SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3442 output_director = false;
3447 Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
3448 SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3449 output_director = false;
3452 Delete(adjustedreturntypeparm);
3456 /* Go through argument list, attach lnames for arguments */
3457 for (i = 0, p = l; p; p = nextSibling(p), ++i) {
3458 String *arg = Getattr(p, "name");
3459 String *lname = NewString("");
3461 if (!arg && Cmp(Getattr(p, "type"), "void")) {
3462 lname = NewStringf("arg%d", i);
3463 Setattr(p, "name", lname);
3467 Setattr(p, "lname", lname);
3470 /* Attach the standard typemaps */
3471 Swig_typemap_attach_parms("out", l, 0);
3472 Swig_typemap_attach_parms("jni", l, 0);
3473 Swig_typemap_attach_parms("jtype", l, 0);
3474 Swig_typemap_attach_parms("directorin", l, 0);
3475 Swig_typemap_attach_parms("javadirectorin", l, 0);
3477 if (!ignored_method) {
3478 /* Add Java environment pointer to wrapper */
3479 String *jenvstr = NewString("jenv");
3480 String *jobjstr = NewString("swigjobj");
3482 Wrapper_add_localv(w, "swigjnienv", "JNIEnvWrapper", "swigjnienv(this)", NIL, NIL);
3483 Wrapper_add_localv(w, jenvstr, "JNIEnv *", jenvstr, "= swigjnienv.getJNIEnv()", NIL);
3484 Wrapper_add_localv(w, jobjstr, "jobject", jobjstr, "= (jobject) NULL", NIL);
3489 Printf(w->code, "if (!swig_override[%d]) {\n", classmeth_off);
3492 if (!pure_virtual) {
3493 String *super_call = Swig_method_call(super, l);
3495 Printf(w->code, "%s;\n", super_call);
3496 if (!ignored_method)
3497 Printf(w->code, "return;\n");
3499 Printf(w->code, "return %s;\n", super_call);
3503 Printf(w->code, "SWIG_JavaThrowException(JNIEnvWrapper(this).getJNIEnv(), SWIG_JavaDirectorPureVirtual, ");
3504 Printf(w->code, "\"Attempted to invoke pure virtual method %s::%s.\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
3506 /* Make sure that we return something in the case of a pure
3507 * virtual method call for syntactical reasons. */
3509 Printf(w->code, "return %s;", qualified_return);
3510 else if (!ignored_method)
3511 Printf(w->code, "return;\n");
3514 if (!ignored_method) {
3515 Printf(w->code, "}\n");
3516 Printf(w->code, "swigjobj = swig_get_self(jenv);\n");
3517 Printf(w->code, "if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) {\n");
3520 /* Start the Java field descriptor for the intermediate class's upcall (insert self object) */
3521 Parm *tp = NewParmFromNode(c_classname, empty_str, n);
3524 if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
3525 && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
3526 String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
3527 Append(jnidesc, jni_canon);
3531 Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
3532 "No or improper directorin typemap for type %s for use in %s::%s (skipping director method)\n",
3533 SwigType_str(type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3534 output_director = false;
3539 /* Go through argument list, convert from native to Java */
3540 for (p = l; p; /* empty */ ) {
3541 /* Is this superfluous? */
3542 while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
3543 p = Getattr(p, "tmap:directorin:next");
3546 SwigType *pt = Getattr(p, "type");
3547 String *ln = Copy(Getattr(p, "name"));
3548 String *c_param_type = NULL;
3549 String *c_decl = NewString("");
3550 String *arg = NewString("");
3552 Printf(arg, "j%s", ln);
3554 /* Add various typemap's 'throws' clauses */
3555 addThrows(n, "tmap:directorin", p);
3556 addThrows(n, "tmap:out", p);
3558 /* And add to the upcall args */
3559 Printf(jupcall_args, ", %s", arg);
3561 /* Get parameter's intermediary C type */
3562 if ((c_param_type = Getattr(p, "tmap:jni"))) {
3563 Parm *tp = NewParmFromNode(c_param_type, empty_str, n);
3564 String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL;
3566 /* Add to local variables */
3567 Printf(c_decl, "%s %s", c_param_type, arg);
3568 if (!ignored_method)
3569 Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
3571 /* Add input marshalling code and update JNI field descriptor */
3572 if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
3573 && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))
3574 && (tm = Getattr(p, "tmap:directorin"))
3575 && (cdesc = Getattr(p, "tmap:directorin:descriptor"))) {
3577 // Objects marshalled by passing a Java class across the JNI boundary use jobject as the JNI type -
3578 // the nouse flag indicates this. We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
3579 if (GetFlag(tp, "tmap:directorin:nouse"))
3581 String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
3582 Append(jnidesc, jni_canon);
3585 Replaceall(tm, "$input", arg);
3586 Replaceall(tm, "$owner", "0");
3589 if (!ignored_method)
3590 Printf(w->code, "%s\n", tm);
3594 /* Add parameter to the intermediate class code if generating the
3595 * intermediate's upcall code */
3596 if ((tm = Getattr(p, "tmap:jtype"))) {
3597 String *din = Copy(Getattr(p, "tmap:javadirectorin"));
3598 addThrows(n, "tmap:javadirectorin", p);
3601 Replaceall(din, "$module", module_class_name);
3602 Replaceall(din, "$imclassname", imclass_name);
3603 substituteClassname(pt, din);
3604 Replaceall(din, "$jniinput", ln);
3607 Printf(imcall_args, ", ");
3608 Printf(callback_def, ", %s %s", tm, ln);
3611 Printv(imcall_args, din, NIL);
3613 Printv(imcall_args, ln, NIL);
3615 jni_canon = canonicalizeJNIDescriptor(cdesc, p);
3616 Append(classdesc, jni_canon);
3619 Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3620 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3621 output_director = false;
3624 Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s for use in %s::%s (skipping director method)\n",
3625 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3626 output_director = false;
3629 p = Getattr(p, "tmap:directorin:next");
3634 Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
3635 "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3636 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3638 } else if (!jdesc) {
3639 Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
3640 "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3641 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3642 p = Getattr(p, "tmap:directorin:next");
3644 Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
3645 "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
3646 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3648 } else if (!cdesc) {
3649 Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
3650 "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3651 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3652 p = Getattr(p, "tmap:directorin:next");
3655 output_director = false;
3660 Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",
3661 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3662 output_director = false;
3668 Delete(c_param_type);
3671 /* header declaration, start wrapper definition */
3673 SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
3674 target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
3675 Printf(w->def, "%s", target);
3676 Delete(qualified_name);
3678 target = Swig_method_decl(rtype, decl, name, l, 0, 1);
3679 Printf(declaration, " virtual %s", target);
3682 // Add any exception specifications to the methods in the director class
3683 // Get any Java exception classes in the throws typemap
3684 ParmList *throw_parm_list = NULL;
3686 if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
3689 Append(w->def, " throw(");
3690 Append(declaration, " throw(");
3692 if (throw_parm_list)
3693 Swig_typemap_attach_parms("throws", throw_parm_list, 0);
3694 for (p = throw_parm_list; p; p = nextSibling(p)) {
3695 if ((tm = Getattr(p, "tmap:throws"))) {
3696 addThrows(n, "tmap:throws", p);
3699 Append(w->def, ", ");
3700 Append(declaration, ", ");
3703 Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
3704 Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
3708 Append(w->def, ")");
3709 Append(declaration, ")");
3712 Append(w->def, " {");
3713 Append(declaration, ";\n");
3715 /* Emit the intermediate class's upcall to the actual class */
3717 String *upcall = NewStringf("self.%s(%s)", symname, imcall_args);
3720 Parm *tp = NewParmFromNode(returntype, empty_str, n);
3722 if ((tm = Swig_typemap_lookup("javadirectorout", tp, "", 0))) {
3723 addThrows(n, "tmap:javadirectorout", tp);
3724 substituteClassname(returntype, tm);
3725 Replaceall(tm, "$javacall", upcall);
3727 Printf(callback_code, " return %s;\n", tm);
3730 if ((tm = Swig_typemap_lookup("out", tp, "", 0)))
3731 addThrows(n, "tmap:out", tp);
3736 Printf(callback_code, " %s;\n", upcall);
3738 Printf(callback_code, " }\n");
3741 /* Finish off the inherited upcall's definition */
3742 Putc(')', callback_def);
3743 generateThrowsClause(n, callback_def);
3744 Printf(callback_def, " {\n");
3746 if (!ignored_method) {
3747 /* Emit the actual upcall through */
3748 String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc);
3749 String *class_desc = NewStringf("(%s)%s", classdesc, classret_desc);
3750 UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, imclass_desc, class_desc, decl);
3751 String *methid = Getattr(udata, "imclass_methodidx");
3752 String *methop = getUpcallJNIMethod(jniret_desc);
3755 Printf(w->code, "jresult = (%s) ", c_ret_type);
3757 Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_methids[%s], %s);\n", methop, imclass_name, methid, jupcall_args);
3759 Printf(w->code, "if (jenv->ExceptionOccurred()) return $null;\n");
3762 String *jresult_str = NewString("jresult");
3763 String *result_str = NewString("c_result");
3764 Parm *tp = NewParmFromNode(returntype, result_str, n);
3766 /* Copy jresult into c_result... */
3767 if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) {
3768 addThrows(n, "tmap:directorout", tp);
3769 Replaceall(tm, "$input", jresult_str);
3770 Replaceall(tm, "$result", result_str);
3771 Printf(w->code, "%s\n", tm);
3773 Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
3774 "Unable to use return type %s used in %s::%s (skipping director method)\n",
3775 SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3776 output_director = false;
3780 Delete(jresult_str);
3784 Delete(imclass_desc);
3787 /* Terminate wrapper code */
3788 Printf(w->code, "} else {\n");
3789 Printf(w->code, "SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"null upcall object\");\n");
3790 Printf(w->code, "}\n");
3792 Printf(w->code, "if (swigjobj) jenv->DeleteLocalRef(swigjobj);\n");
3795 Printf(w->code, "return %s;", qualified_return);
3798 Printf(w->code, "}");
3800 // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
3801 String *inline_extra_method = NewString("");
3802 if (dirprot_mode() && !is_public(n) && !pure_virtual) {
3803 Printv(inline_extra_method, declaration, NIL);
3804 String *extra_method_name = NewStringf("%sSwigPublic", name);
3805 Replaceall(inline_extra_method, name, extra_method_name);
3806 Replaceall(inline_extra_method, ";\n", " {\n ");
3808 Printf(inline_extra_method, "return ");
3809 String *methodcall = Swig_method_call(super, l);
3810 Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
3812 Delete(extra_method_name);
3816 if (status == SWIG_OK && output_director) {
3818 Replaceall(w->code, "$null", qualified_return);
3820 Replaceall(w->code, "$null", "");
3822 if (!GetFlag(n, "feature:ignore"))
3823 Printv(imclass_directors, callback_def, callback_code, NIL);
3824 if (!Getattr(n, "defaultargs")) {
3825 Wrapper_print(w, f_directors);
3826 Printv(f_directors_h, declaration, NIL);
3827 Printv(f_directors_h, inline_extra_method, NIL);
3831 Delete(inline_extra_method);
3832 Delete(qualified_return);
3835 Delete(jniret_desc);
3836 Delete(declaration);
3837 Delete(callback_def);
3838 Delete(callback_code);
3844 /* ------------------------------------------------------------
3845 * directorPrefixArgs()
3846 * ------------------------------------------------------------ */
3848 void directorPrefixArgs(Node *n) {
3851 /* Need to prepend 'jenv' to the director constructor's argument list */
3853 String *jenv_type = NewString("JNIEnv");
3855 SwigType_add_pointer(jenv_type);
3857 p = NewParmFromNode(jenv_type, NewString("jenv"), n);
3858 Setattr(p, "arg:byname", "1");
3859 set_nextSibling(p, NULL);
3861 Setattr(n, "director:prefix_args", p);
3864 /* ------------------------------------------------------------
3865 * classDirectorConstructor()
3866 * ------------------------------------------------------------ */
3868 int classDirectorConstructor(Node *n) {
3869 Node *parent = parentNode(n);
3870 String *decl = Getattr(n, "decl");;
3871 String *supername = Swig_class_name(parent);
3872 String *classname = directorClassName(parent);
3873 String *sub = NewString("");
3875 ParmList *superparms = Getattr(n, "parms");
3879 /* Assign arguments to superclass's parameters, if not already done */
3880 for (p = superparms; p; p = nextSibling(p)) {
3881 String *pname = Getattr(p, "name");
3884 pname = NewStringf("arg%d", argidx++);
3885 Setattr(p, "name", pname);
3889 /* insert jenv prefix argument */
3890 parms = CopyParmList(superparms);
3892 String *jenv_type = NewString("JNIEnv");
3893 SwigType_add_pointer(jenv_type);
3894 p = NewParmFromNode(jenv_type, NewString("jenv"), n);
3895 set_nextSibling(p, parms);
3898 directorPrefixArgs(n);
3900 if (!Getattr(n, "defaultargs")) {
3903 String *basetype = Getattr(parent, "classtype");
3904 String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
3905 String *call = Swig_csuperclass_call(0, basetype, superparms);
3906 String *classtype = SwigType_namestr(Getattr(n, "name"));
3908 Printf(f_directors, "%s::%s : %s, %s {\n", classname, target, call, Getattr(parent, "director:ctor"));
3909 Printf(f_directors, "}\n\n");
3916 /* constructor header */
3918 String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
3919 Printf(f_directors_h, " %s;\n", target);
3928 return Language::classDirectorConstructor(n);
3931 /* ------------------------------------------------------------
3932 * classDirectorDefaultConstructor()
3933 * ------------------------------------------------------------ */
3935 int classDirectorDefaultConstructor(Node *n) {
3936 String *classname = Swig_class_name(n);
3937 String *classtype = SwigType_namestr(Getattr(n, "name"));
3938 Wrapper *w = NewWrapper();
3940 Printf(w->def, "SwigDirector_%s::SwigDirector_%s(JNIEnv *jenv) : %s {", classname, classname, Getattr(n, "director:ctor"));
3941 Printf(w->code, "}\n");
3942 Wrapper_print(w, f_directors);
3944 Printf(f_directors_h, " SwigDirector_%s(JNIEnv *jenv);\n", classname);
3948 directorPrefixArgs(n);
3949 return Language::classDirectorDefaultConstructor(n);
3953 /* ------------------------------------------------------------
3954 * classDirectorInit()
3955 * ------------------------------------------------------------ */
3957 int classDirectorInit(Node *n) {
3958 Delete(none_comparison);
3959 none_comparison = NewString(""); // not used
3961 Delete(director_ctor_code);
3962 director_ctor_code = NewString("$director_new");
3964 Java_director_declaration(n);
3966 Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
3967 Printf(f_directors_h, "\npublic:\n");
3968 Printf(f_directors_h, " void swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global);\n");
3970 /* Keep track of the director methods for this class */
3971 first_class_dmethod = curr_class_dmethod = n_dmethods;
3973 return Language::classDirectorInit(n);
3976 /* ----------------------------------------------------------------------
3977 * classDirectorDestructor()
3978 * ---------------------------------------------------------------------- */
3980 int classDirectorDestructor(Node *n) {
3981 Node *current_class = getCurrentClass();
3982 String *full_classname = Getattr(current_class, "name");
3983 String *classname = Swig_class_name(current_class);
3984 Wrapper *w = NewWrapper();
3986 if (Getattr(n, "throw")) {
3987 Printf(f_directors_h, " virtual ~SwigDirector_%s() throw ();\n", classname);
3988 Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() throw () {\n", classname, classname);
3990 Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname);
3991 Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname);
3994 /* Ensure that correct directordisconnect typemap's method name is called
3997 const String *disconn_tm = NULL;
3998 Node *disconn_attr = NewHash();
3999 String *disconn_methodname = NULL;
4001 disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
4002 disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
4004 Printv(w->code, " swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL);
4006 Wrapper_print(w, f_directors);
4009 Delete(disconn_attr);
4014 /* ------------------------------------------------------------
4015 * classDirectorEnd()
4016 * ------------------------------------------------------------ */
4018 int classDirectorEnd(Node *n) {
4019 String *classname = Getattr(n, "sym:name");
4020 String *director_classname = directorClassName(n);
4021 String *internal_classname;
4023 Wrapper *w = NewWrapper();
4025 if (Len(package_path) > 0)
4026 internal_classname = NewStringf("%s/%s", package_path, classname);
4028 internal_classname = NewStringf("%s", classname);
4030 Wrapper_add_localv(w, "baseclass", "static jclass baseclass", "= 0", NIL);
4031 Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname);
4033 if (first_class_dmethod != curr_class_dmethod) {
4034 Printf(w->def, "static struct {\n");
4035 Printf(w->def, "const char *mname;\n");
4036 Printf(w->def, "const char *mdesc;\n");
4037 Printf(w->def, "jmethodID base_methid;\n");
4038 Printf(w->def, "} methods[] = {\n");
4040 for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
4041 UpcallData *udata = Getitem(dmethods_seq, i);
4043 Printf(w->def, "{ \"%s\", \"%s\", NULL }", Getattr(udata, "method"), Getattr(udata, "fdesc"));
4044 if (i != curr_class_dmethod - 1)
4049 Printf(w->def, "};\n");
4052 Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\n");
4053 Printf(w->code, "if (!baseclass) {\n");
4054 Printf(w->code, "baseclass = jenv->FindClass(\"%s\");\n", internal_classname);
4055 Printf(w->code, "if (!baseclass) return;\n");
4056 Printf(w->code, "baseclass = (jclass) jenv->NewGlobalRef(baseclass);\n");
4057 Printf(w->code, "}\n");
4059 int n_methods = curr_class_dmethod - first_class_dmethod;
4062 /* Emit the swig_overrides() method and the swig_override array */
4063 Printf(f_directors_h, "public:\n");
4064 Printf(f_directors_h, " bool swig_overrides(int n) {\n");
4065 Printf(f_directors_h, " return (n < %d ? swig_override[n] : false);\n", n_methods);
4066 Printf(f_directors_h, " }\n");
4067 Printf(f_directors_h, "protected:\n");
4068 Printf(f_directors_h, " bool swig_override[%d];\n", n_methods);
4070 /* Emit the code to look up the class's methods, initialize the override array */
4072 Printf(w->code, "bool derived = (jenv->IsSameObject(baseclass, jcls) ? false : true);\n");
4073 Printf(w->code, "for (int i = 0; i < %d; ++i) {\n", n_methods);
4074 Printf(w->code, " if (!methods[i].base_methid) {\n");
4075 Printf(w->code, " methods[i].base_methid = jenv->GetMethodID(baseclass, methods[i].mname, methods[i].mdesc);\n");
4076 Printf(w->code, " if (!methods[i].base_methid) return;\n");
4077 Printf(w->code, " }\n");
4078 Printf(w->code, " swig_override[i] = false;\n");
4079 Printf(w->code, " if (derived) {\n");
4080 Printf(w->code, " jmethodID methid = jenv->GetMethodID(jcls, methods[i].mname, methods[i].mdesc);\n");
4081 Printf(w->code, " swig_override[i] = (methid != methods[i].base_methid);\n");
4082 Printf(w->code, " jenv->ExceptionClear();\n");
4083 Printf(w->code, " }\n");
4084 Printf(w->code, "}\n");
4086 Printf(f_directors_h, "public:\n");
4087 Printf(f_directors_h, " bool swig_overrides(int n) {\n");
4088 Printf(f_directors_h, " return false;\n");
4089 Printf(f_directors_h, " }\n");
4092 Printf(f_directors_h, "};\n\n");
4093 Printf(w->code, "}\n");
4094 Printf(w->code, "}\n");
4096 Wrapper_print(w, f_directors);
4099 Delete(internal_classname);
4101 return Language::classDirectorEnd(n);
4104 /* --------------------------------------------------------------------
4105 * classDirectorDisown()
4106 * ------------------------------------------------------------------*/
4108 virtual int classDirectorDisown(Node *n) {
4113 /*----------------------------------------------------------------------
4114 * extraDirectorProtectedCPPMethodsRequired()
4115 *--------------------------------------------------------------------*/
4116 bool extraDirectorProtectedCPPMethodsRequired() const {
4120 /*----------------------------------------------------------------------
4121 * Java_director_declaration()
4123 * Generate the director class's declaration
4124 * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
4125 *--------------------------------------------------------------------*/
4127 void Java_director_declaration(Node *n) {
4128 String *base = Getattr(n, "classtype");
4129 String *class_ctor = NewString("Swig::Director(jenv)");
4131 String *classname = Swig_class_name(n);
4132 String *directorname = NewStringf("SwigDirector_%s", classname);
4133 String *declaration = Swig_class_declaration(n, directorname);
4135 Printf(declaration, " : public %s, public Swig::Director", base);
4137 // Stash stuff for later.
4138 Setattr(n, "director:decl", declaration);
4139 Setattr(n, "director:ctor", class_ctor);
4144 /* -----------------------------------------------------------------------------
4145 * swig_java() - Instantiate module
4146 * ----------------------------------------------------------------------------- */
4148 static Language *new_swig_java() {
4151 extern "C" Language *swig_java(void) {
4152 return new_swig_java();
4155 /* -----------------------------------------------------------------------------
4156 * Static member variables
4157 * ----------------------------------------------------------------------------- */
4159 const char *JAVA::usage = (char *) "\
4160 Java Options (available with -java)\n\
4161 -nopgcpp - Suppress premature garbage collection prevention parameter\n\
4162 -noproxy - Generate the low-level functional interface instead\n\
4164 -oldvarnames - old intermediary method names for variable wrappers\n\
4165 -package <name> - set name of the Java package to <name>\n\