diff --git a/Lib/csharp/feature_interface.i b/Lib/csharp/feature_interface.i index 0c95feb93..89d2dbffe 100644 --- a/Lib/csharp/feature_interface.i +++ b/Lib/csharp/feature_interface.i @@ -1,5 +1,5 @@ %define DECLARE_INTERFACE_(INTERFACE, IMPL, CTYPE...) -%feature("interface", name = "INTERFACE", cptr = "SWIGInterfaceUpcast") CTYPE; +%feature("interface", name="INTERFACE") CTYPE; %typemap(cstype) CTYPE, CTYPE *, CTYPE [], CTYPE &, CTYPE *const& "INTERFACE" %typemap(csin) CTYPE, CTYPE & "$csinput.SWIGInterfaceUpcast()" %typemap(csin) CTYPE *, CTYPE *const&, CTYPE [] "$csinput == null ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : $csinput.SWIGInterfaceUpcast()" @@ -19,6 +19,12 @@ %typemap(csdirectorin) CTYPE, CTYPE & "(INTERFACE)new IMPL($iminput, false)" %typemap(csdirectorin) CTYPE *, CTYPE *const&, CTYPE [] "($iminput == global::System.IntPtr.Zero) ? null : (INTERFACE)new IMPL($iminput, false)" %typemap(csdirectorout) CTYPE, CTYPE *, CTYPE *const&, CTYPE [], CTYPE & "$cscall.SWIGInterfaceUpcast()" +%typemap(csinterfacecode, declaration=" [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n global::System.Runtime.InteropServices.HandleRef SWIGInterfaceUpcast();\n", cptrmethod="$interfacename_SWIGInterfaceUpcast") CTYPE %{ + [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] + global::System.Runtime.InteropServices.HandleRef $interfacename.SWIGInterfaceUpcast() { + return new global::System.Runtime.InteropServices.HandleRef(($interfacename)this, $imclassname.$csclazzname$interfacename_SWIGInterfaceUpcast(swigCPtr.Handle)); + } +%} %enddef %define DECLARE_INTERFACE_RENAME(INTERFACE, IMPL, CTYPE...) diff --git a/Lib/java/feature_interface.i b/Lib/java/feature_interface.i index a6b46effa..1359db503 100644 --- a/Lib/java/feature_interface.i +++ b/Lib/java/feature_interface.i @@ -1,5 +1,5 @@ %define DECLARE_INTERFACE_(INTERFACE, IMPL, CTYPE...) -%feature("interface", name = "INTERFACE", cptr = #INTERFACE ## "_SWIGInterfaceUpcast") CTYPE; +%feature("interface", name="INTERFACE") CTYPE; %typemap(jtype, nopgcpp="1") CTYPE, CTYPE *, CTYPE *const&, CTYPE [], CTYPE & "long" %typemap(jstype) CTYPE, CTYPE *, CTYPE *const&, CTYPE [], CTYPE & "INTERFACE" %typemap(javain) CTYPE, CTYPE & "$javainput." ## #INTERFACE ## "_SWIGInterfaceUpcast()" @@ -21,6 +21,11 @@ %{ $input = 0; *(($&1_ltype*)&$input) = &$1; %} +%typemap(javainterfacecode, declaration=" long $interfacename_SWIGInterfaceUpcast();\n", cptrmethod="$interfacename_SWIGInterfaceUpcast") CTYPE %{ + public long $interfacename_SWIGInterfaceUpcast() { + return $imclassname.$javaclazzname$interfacename_SWIGInterfaceUpcast(swigCPtr); + } +%} SWIG_JAVABODY_PROXY(public, protected, CTYPE) %enddef diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h index bc54bc774..865655896 100644 --- a/Source/Include/swigwarn.h +++ b/Source/Include/swigwarn.h @@ -256,6 +256,7 @@ #define WARN_JAVA_TYPEMAP_JAVAIN_UNDEF 818 #define WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF 819 #define WARN_JAVA_TYPEMAP_JAVADIRECTOROUT_UNDEF 820 +#define WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF 821 #define WARN_JAVA_COVARIANT_RET 822 #define WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF 823 #define WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC 824 @@ -275,6 +276,7 @@ #define WARN_CSHARP_TYPEMAP_CSIN_UNDEF 838 #define WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF 839 #define WARN_CSHARP_TYPEMAP_CSDIRECTOROUT_UNDEF 840 +#define WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF 841 #define WARN_CSHARP_COVARIANT_RET 842 #define WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF 843 #define WARN_CSHARP_EXCODE 844 diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx index 8d2d434f3..10b98d279 100644 --- a/Source/Modules/csharp.cxx +++ b/Source/Modules/csharp.cxx @@ -1647,6 +1647,10 @@ public: return Language::pragmaDirective(n); } + /* ----------------------------------------------------------------------------- + * getQualifiedInterfaceName() + * ----------------------------------------------------------------------------- */ + String *getQualifiedInterfaceName(Node *n) { String *ret = Getattr(n, "interface:qname"); if (!ret) { @@ -1665,6 +1669,10 @@ public: return ret; } + /* ----------------------------------------------------------------------------- + * addInterfaceNameAndUpcasts() + * ----------------------------------------------------------------------------- */ + void addInterfaceNameAndUpcasts(String *interface_list, String *interface_upcasts, Hash *base_list, String *c_classname) { List *keys = Keys(base_list); for (Iterator it = First(keys); it.item; it = Next(it)) { @@ -1675,19 +1683,22 @@ public: Append(interface_list, ", "); Append(interface_list, interface_name); - Printf(interface_upcasts, "\n"); - Printf(interface_upcasts, " [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n"); - String *upcast_name = 0; - if (String *cptr_func = Getattr(base, "feature:interface:cptr")) - upcast_name = NewStringf("%s.%s", interface_name, cptr_func); - else - upcast_name = NewStringf("%s.SWIGInterfaceUpcast", interface_name); - Printf(interface_upcasts, " global::System.Runtime.InteropServices.HandleRef %s() {\n", upcast_name); - Replaceall(upcast_name, ".", "_"); - String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, upcast_name); + Node *attributes = NewHash(); + String *interface_code = Copy(typemapLookup(base, "csinterfacecode", Getattr(base, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes)); + String *cptr_method_name = 0; + if (interface_code) { + Replaceall(interface_code, "$interfacename", interface_name); + Printv(interface_upcasts, interface_code, NIL); + cptr_method_name = Copy(Getattr(attributes, "tmap:csinterfacecode:cptrmethod")); + } + if (!cptr_method_name) + cptr_method_name = NewString("$interfacename_GetInterfaceCPtr"); + Replaceall(cptr_method_name, "$interfacename", interface_name); + Replaceall(cptr_method_name, ".", "_"); + + String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name); String *wname = Swig_name_wrapper(upcast_method); - Printf(interface_upcasts, " return new global::System.Runtime.InteropServices.HandleRef((%s)this, %s.%s(swigCPtr.Handle));\n", interface_name, imclass_name, upcast_method); - Printf(interface_upcasts, " }\n"); + Printv(imclass_cppcasts_code, "\n [global::System.Runtime.InteropServices.DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL); Printf(imclass_cppcasts_code, " public static extern global::System.IntPtr %s(global::System.IntPtr jarg1);\n", upcast_method); Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); @@ -1695,7 +1706,9 @@ public: "SWIGEXPORT ", c_baseclass, " * SWIGSTDCALL ", wname, "(", c_classname, " *jarg1) {\n", " return (", c_baseclass, " *)jarg1;\n" "}\n", "\n", NIL); - Delete(upcast_name); + + Delete(interface_code); + Delete(cptr_method_name); Delete(wname); Delete(upcast_method); Delete(c_baseclass); @@ -1742,7 +1755,7 @@ public: /* Warn about multiple inheritance for additional base class(es) */ String *proxyclassname = Getattr(n, "classtypeobj"); Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n), - "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname)); + "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname)); } } base = Next(base); @@ -1966,6 +1979,10 @@ public: Delete(baseclass); } + /* ---------------------------------------------------------------------- + * emitInterfaceDeclaration() + * ---------------------------------------------------------------------- */ + void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface) { Printv(f_interface, typemapLookup(n, "csimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL); Printf(f_interface, "public interface %s", interface_name); @@ -1988,13 +2005,24 @@ public: } } Printf(f_interface, " {\n"); - Printf(f_interface, " [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]\n"); - if (String *cptr_func = Getattr(n, "feature:interface:cptr")) - Printf(f_interface, " global::System.Runtime.InteropServices.HandleRef %s();\n", cptr_func); - else - Printf(f_interface, " global::System.Runtime.InteropServices.HandleRef SWIGInterfaceUpcast();\n"); + + Node *attributes = NewHash(); + String *interface_code = Copy(typemapLookup(n, "csinterfacecode", Getattr(n, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACECODE_UNDEF, attributes)); + if (interface_code) { + String *interface_declaration = Copy(Getattr(attributes, "tmap:csinterfacecode:declaration")); + if (interface_declaration) { + Replaceall(interface_declaration, "$interfacename", interface_name); + Printv(f_interface, interface_declaration, NIL); + Delete(interface_declaration); + } + Delete(interface_code); + } } + /* ---------------------------------------------------------------------- + * calculateDirectBase() + * ---------------------------------------------------------------------- */ + void calculateDirectBase(Node* n) { Node* direct_base = 0; // C++ inheritance @@ -2026,6 +2054,7 @@ public: virtual int classHandler(Node *n) { String *nspace = getNSpace(); File *f_proxy = NULL; + File *f_interface = NULL; // save class local variables String *old_proxy_class_name = proxy_class_name; String *old_full_imclass_name = full_imclass_name; @@ -2034,7 +2063,6 @@ public: String *old_proxy_class_def = proxy_class_def; String *old_proxy_class_code = proxy_class_code; bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested"); - File *f_interface = NULL; String *old_interface_class_code = interface_class_code; interface_class_code = 0; @@ -2093,12 +2121,13 @@ public: proxy_class_constants_code = NewString(""); if (Getattr(n, "feature:interface")) { - interface_class_code = NewStringEmpty(); + interface_class_code = NewString(""); String *interface_name = Getattr(n, "feature:interface:name"); + // TODO check feature:interface:name is not missing String *output_directory = outputDirectory(nspace); f_interface = getOutputFile(output_directory, interface_name); addOpenNamespace(nspace, f_interface); - emitInterfaceDeclaration(n, interface_name, f_interface); + emitInterfaceDeclaration(n, interface_name, interface_class_code); Delete(output_directory); } calculateDirectBase(n); @@ -2115,22 +2144,28 @@ public: Replaceall(proxy_class_def, "$csclassname", proxy_class_name); Replaceall(proxy_class_code, "$csclassname", proxy_class_name); Replaceall(proxy_class_constants_code, "$csclassname", proxy_class_name); + Replaceall(interface_class_code, "$csclassname", proxy_class_name); Replaceall(proxy_class_def, "$csclazzname", csclazzname); Replaceall(proxy_class_code, "$csclazzname", csclazzname); Replaceall(proxy_class_constants_code, "$csclazzname", csclazzname); + Replaceall(interface_class_code, "$csclazzname", csclazzname); Replaceall(proxy_class_def, "$module", module_class_name); Replaceall(proxy_class_code, "$module", module_class_name); Replaceall(proxy_class_constants_code, "$module", module_class_name); + Replaceall(interface_class_code, "$module", module_class_name); Replaceall(proxy_class_def, "$imclassname", full_imclass_name); Replaceall(proxy_class_code, "$imclassname", full_imclass_name); Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name); + Replaceall(interface_class_code, "$imclassname", full_imclass_name); Replaceall(proxy_class_def, "$dllimport", dllimport); Replaceall(proxy_class_code, "$dllimport", dllimport); Replaceall(proxy_class_constants_code, "$dllimport", dllimport); + Replaceall(interface_class_code, "$dllimport", dllimport); + if (!has_outerclass) Printv(f_proxy, proxy_class_def, proxy_class_code, NIL); else { @@ -2198,6 +2233,7 @@ public: addCloseNamespace(nspace, f_interface); if (f_interface != f_single_out) Delete(f_interface); + f_interface = 0; } emitDirectorExtraMethods(n); diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index cd6c7d84b..9a650dc6f 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -1729,6 +1729,10 @@ public: return Language::pragmaDirective(n); } + /* ----------------------------------------------------------------------------- + * getQualifiedInterfaceName() + * ----------------------------------------------------------------------------- */ + String *getQualifiedInterfaceName(Node *n) { String *ret = Getattr(n, "interface:qname"); if (!ret) { @@ -1750,8 +1754,11 @@ public: return ret; } + /* ----------------------------------------------------------------------------- + * addInterfaceNameAndUpcasts() + * ----------------------------------------------------------------------------- */ + void addInterfaceNameAndUpcasts(String *interface_list, String *interface_upcasts, Hash *base_list, String *c_classname) { -// Printf(stdout, "addInterfaceNameAndUpcasts %s base_list", c_classname); List *keys = Keys(base_list); for (Iterator it = First(keys); it.item; it = Next(it)) { Node *base = Getattr(base_list, it.item); @@ -1761,21 +1768,26 @@ public: Append(interface_list, ", "); Append(interface_list, interface_name); - String *upcast_name = 0; - if (String *cptr_func = Getattr(base, "feature:interface:cptr")) - upcast_name = NewStringf("%s", cptr_func); - else - upcast_name = NewStringf("%s_SWIGInterfaceUpcast", interface_name); - Printf(interface_upcasts, "\n"); - Printf(interface_upcasts, " public long %s() {\n", upcast_name); - Replaceall(upcast_name, ".", "_"); - String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, upcast_name); + Node *attributes = NewHash(); + String *interface_code = Copy(typemapLookup(base, "javainterfacecode", Getattr(base, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes)); + String *cptr_method_name = 0; + if (interface_code) { + Replaceall(interface_code, "$interfacename", interface_name); + Printv(interface_upcasts, interface_code, NIL); + cptr_method_name = Copy(Getattr(attributes, "tmap:javainterfacecode:cptrmethod")); + } + if (!cptr_method_name) + cptr_method_name = NewString("$interfacename_GetInterfaceCPtr"); + Replaceall(cptr_method_name, "$interfacename", interface_name); + Replaceall(cptr_method_name, ".", "_"); + + String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name); String *jniname = makeValidJniName(upcast_method); String *wname = Swig_name_wrapper(jniname); - Printf(interface_upcasts, " return %s.%s(swigCPtr);\n", imclass_name, upcast_method); - Printf(interface_upcasts, " }\n"); + Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method); - Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name); + Replaceall(imclass_cppcasts_code, "$javaclassname", proxy_class_name); + Printv(upcasts_code, "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", " jlong baseptr = 0;\n" @@ -1784,13 +1796,14 @@ public: " *(", c_baseclass, " **)&baseptr = *(", c_classname, " **)&jarg1;\n" " return baseptr;\n" "}\n", "\n", NIL); - Delete(upcast_name); + + Delete(interface_code); + Delete(cptr_method_name); Delete(wname); Delete(jniname); Delete(upcast_method); Delete(c_baseclass); } -// Printf(stdout, " => %s\n", interface_list); Delete(keys); } @@ -1998,6 +2011,10 @@ public: Delete(baseclass); } + /* ---------------------------------------------------------------------- + * emitInterfaceDeclaration() + * ---------------------------------------------------------------------- */ + void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface, String *nspace) { if (package || nspace) { Printf(f_interface, "package "); @@ -2029,24 +2046,37 @@ public: } } Printf(f_interface, " {\n"); - if (String *cptr_func = Getattr(n, "feature:interface:cptr")) - Printf(f_interface, " long %s();\n", cptr_func); - else - Printf(f_interface, " long %s_SWIGInterfaceUpcast();\n", interface_name); + + Node *attributes = NewHash(); + String *interface_code = Copy(typemapLookup(n, "javainterfacecode", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes)); + if (interface_code) { + String *interface_declaration = Copy(Getattr(attributes, "tmap:javainterfacecode:declaration")); + if (interface_declaration) { + Replaceall(interface_declaration, "$interfacename", interface_name); + Printv(f_interface, interface_declaration, NIL); + Delete(interface_declaration); + } + Delete(interface_code); + } } + /* ---------------------------------------------------------------------- + * classDeclaration() + * ---------------------------------------------------------------------- */ + int classDeclaration(Node *n) { if (proxy_flag) Swig_propagate_interface_methods(n); return Language::classDeclaration(n); } - /* ---------------------------------------------------------------------- - * classHandler() - * ---------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------- + * classHandler() + * ---------------------------------------------------------------------- */ virtual int classHandler(Node *n) { File *f_proxy = NULL; + File *f_interface = NULL; String *old_proxy_class_name = proxy_class_name; String *old_full_proxy_class_name = full_proxy_class_name; String *old_full_imclass_name = full_imclass_name; @@ -2056,7 +2086,7 @@ public: String *old_proxy_class_def = proxy_class_def; String *old_proxy_class_code = proxy_class_code; bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested"); - File *f_interface = NULL; + String *old_interface_class_code = interface_class_code; interface_class_code = 0; if (proxy_flag) { @@ -2146,8 +2176,9 @@ public: proxy_class_constants_code = NewString(""); if (Getattr(n, "feature:interface")) { - interface_class_code = NewStringEmpty(); + interface_class_code = NewString(""); String *interface_name = Getattr(n, "feature:interface:name"); + // TODO check feature:interface:name is not missing String *output_directory = outputDirectory(nspace); String *filen = NewStringf("%s%s.java", output_directory, interface_name); f_interface = NewFile(filen, "w", SWIG_output_files()); @@ -2157,7 +2188,7 @@ public: } Append(filenames_list, filen); // file name ownership goes to the list emitBanner(f_interface); - emitInterfaceDeclaration(n, interface_name, f_interface, nspace); + emitInterfaceDeclaration(n, interface_name, interface_class_code, nspace); Delete(filen); Delete(output_directory); } @@ -2166,7 +2197,6 @@ public: Language::classHandler(n); if (proxy_flag) { - emitProxyClassDefAndCPPCasts(n); String *javaclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name @@ -2174,18 +2204,22 @@ public: Replaceall(proxy_class_def, "$javaclassname", proxy_class_name); Replaceall(proxy_class_code, "$javaclassname", proxy_class_name); Replaceall(proxy_class_constants_code, "$javaclassname", proxy_class_name); + Replaceall(interface_class_code, "$javaclassname", proxy_class_name); Replaceall(proxy_class_def, "$javaclazzname", javaclazzname); Replaceall(proxy_class_code, "$javaclazzname", javaclazzname); Replaceall(proxy_class_constants_code, "$javaclazzname", javaclazzname); + Replaceall(interface_class_code, "$javaclazzname", javaclazzname); Replaceall(proxy_class_def, "$module", module_class_name); Replaceall(proxy_class_code, "$module", module_class_name); Replaceall(proxy_class_constants_code, "$module", module_class_name); + Replaceall(interface_class_code, "$module", module_class_name); Replaceall(proxy_class_def, "$imclassname", full_imclass_name); Replaceall(proxy_class_code, "$imclassname", full_imclass_name); Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name); + Replaceall(interface_class_code, "$imclassname", full_imclass_name); if (!has_outerclass) Printv(f_proxy, proxy_class_def, proxy_class_code, NIL); @@ -2253,10 +2287,13 @@ public: if (f_interface) { Printv(f_interface, interface_class_code, "}\n", NIL); Delete(f_interface); + f_interface = 0; } emitDirectorExtraMethods(n); + Delete(interface_class_code); + interface_class_code = old_interface_class_code; Delete(javaclazzname); Delete(proxy_class_name); proxy_class_name = old_proxy_class_name;