Merge branch 'interfaces' into interfaces2
* interfaces: Remove unnecessary interfaces for concrete classes cosmetic code formatting changes Correct interface name attributes that are internal interface macro changes to support templates Test non-virtual method in Derived classes interface tests for a most derived class inheriting the interfaces further up the chain Rename GetCPtr/getCPtr to SWIGInterfaceUpcast interface feature support for const ref pointers (used by the STL) Interface feature support for arrays More interface feature testing for return values interface feature support for passing by value interface feature support for references Multiple inheritance parameters as pointers testing Simplify multiple_inheritance_abstract Java runtime test Warning fixes Rename test functions in multiple_inheritance_abstract testcase Formatting fixes in generated code for interface feature Cosmetic spacing changes in test case interface feature typemap corrections to handle NULL pointers interface test added javadirectorin fix interface implementation visibility interface inheritance (2) interface inheritance (1) feature:interface ported to Java propagate non-abstract "interface" base methods (3) propagate non-abstract "interface" base methods (2) propagate non-abstract "interface" base methods (1) namespace support added GetCPtr now returns HandleRef "feature:interface:name" is now mandatory attribute interfaces (1) interfaces (1) Conflicts: Source/Modules/csharp.cxx Source/Modules/java.cxx
This commit is contained in:
commit
abccc13a4a
11 changed files with 1166 additions and 39 deletions
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
/* Hash type used for upcalls from C/C++ */
|
||||
typedef DOH UpcallData;
|
||||
// helper function used in feature:interface implementation
|
||||
void Swig_propagate_interface_methods(Node *n);
|
||||
|
||||
class CSHARP:public Language {
|
||||
static const char *usage;
|
||||
|
|
@ -52,6 +54,7 @@ class CSHARP:public Language {
|
|||
String *imclass_class_code; // intermediary class code
|
||||
String *proxy_class_def;
|
||||
String *proxy_class_code;
|
||||
String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
|
||||
String *module_class_code;
|
||||
String *proxy_class_name; // proxy class name
|
||||
String *full_imclass_name; // fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
|
||||
|
|
@ -126,6 +129,7 @@ public:
|
|||
imclass_class_code(NULL),
|
||||
proxy_class_def(NULL),
|
||||
proxy_class_code(NULL),
|
||||
interface_class_code(NULL),
|
||||
module_class_code(NULL),
|
||||
proxy_class_name(NULL),
|
||||
full_imclass_name(NULL),
|
||||
|
|
@ -1643,6 +1647,62 @@ public:
|
|||
return Language::pragmaDirective(n);
|
||||
}
|
||||
|
||||
String *getQualifiedInterfaceName(Node *n) {
|
||||
String *ret = Getattr(n, "interface:qname");
|
||||
if (!ret) {
|
||||
String *nspace = Getattr(n, "sym:nspace");
|
||||
String *iname = Getattr(n, "feature:interface:name");
|
||||
if (nspace) {
|
||||
if (namespce)
|
||||
ret = NewStringf("%s.%s.%s", namespce, nspace, iname);
|
||||
else
|
||||
ret = NewStringf("%s.%s", nspace, iname);
|
||||
} else {
|
||||
ret = Copy(iname);
|
||||
}
|
||||
Setattr(n, "interface:qname", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)) {
|
||||
Node *base = Getattr(base_list, it.item);
|
||||
String *c_baseclass = SwigType_namestr(Getattr(base, "name"));
|
||||
String *iname = getQualifiedInterfaceName(base);
|
||||
if (Len(interface_list))
|
||||
Append(interface_list, ", ");
|
||||
Append(interface_list, iname);
|
||||
|
||||
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", iname, cptr_func);
|
||||
else
|
||||
upcast_name = NewStringf("%s.SWIGInterfaceUpcast", iname);
|
||||
Printf(interface_upcasts, " HandleRef %s() {\n", upcast_name);
|
||||
Replaceall(upcast_name, ".", "_");
|
||||
String *upcast_method = Swig_name_member(getNSpace(), proxy_class_name, upcast_name);
|
||||
String *wname = Swig_name_wrapper(upcast_method);
|
||||
Printf(interface_upcasts, " return new HandleRef((%s)this, %s.%s(swigCPtr.Handle));\n", iname, imclass_name, upcast_method);
|
||||
Printf(interface_upcasts, " }\n");
|
||||
Printv(imclass_cppcasts_code, "\n [DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
|
||||
Printf(imclass_cppcasts_code, " public static extern IntPtr %s(IntPtr jarg1);\n", upcast_method);
|
||||
Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT ", c_baseclass, " * SWIGSTDCALL ", wname, "(", c_classname, " *jarg1) {\n",
|
||||
" return (", c_baseclass, " *)jarg1;\n"
|
||||
"}\n", "\n", NIL);
|
||||
Delete(upcast_name);
|
||||
Delete(wname);
|
||||
Delete(upcast_method);
|
||||
Delete(c_baseclass);
|
||||
}
|
||||
Delete(keys);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitProxyClassDefAndCPPCasts()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
@ -1652,6 +1712,8 @@ public:
|
|||
String *c_baseclass = NULL;
|
||||
String *baseclass = NULL;
|
||||
String *c_baseclassname = NULL;
|
||||
String *interface_list = NewStringEmpty();
|
||||
String *interface_upcasts = NewStringEmpty();
|
||||
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
|
||||
bool feature_director = Swig_directorclass(n) ? true : false;
|
||||
bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
|
||||
|
|
@ -1668,9 +1730,8 @@ public:
|
|||
List *baselist = Getattr(n, "bases");
|
||||
if (baselist) {
|
||||
Iterator base = First(baselist);
|
||||
while (base.item && GetFlag(base.item, "feature:ignore")) {
|
||||
base = Next(base);
|
||||
}
|
||||
while (base.item && (GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface")))
|
||||
base = Next(base);
|
||||
if (base.item) {
|
||||
c_baseclassname = Getattr(base.item, "name");
|
||||
baseclass = Copy(getProxyName(c_baseclassname));
|
||||
|
|
@ -1679,19 +1740,20 @@ public:
|
|||
base = Next(base);
|
||||
/* Warn about multiple inheritance for additional base class(es) */
|
||||
while (base.item) {
|
||||
if (GetFlag(base.item, "feature:ignore")) {
|
||||
base = Next(base);
|
||||
continue;
|
||||
}
|
||||
String *proxyclassname = Getattr(n, "classtypeobj");
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
|
||||
if (!GetFlag(base.item, "feature:ignore") && !Getattr(base.item, "feature:interface")) {
|
||||
String *proxyclassname = Getattr(n, "classtypeobj");
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
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));
|
||||
}
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Hash *interface_bases = Getattr(n, "interface:bases");
|
||||
if (interface_bases)
|
||||
addInterfaceNameAndUpcasts(interface_list, interface_upcasts, interface_bases, c_classname);
|
||||
|
||||
bool derived = baseclass && getProxyName(c_baseclassname);
|
||||
if (derived && purebase_notderived)
|
||||
|
|
@ -1713,6 +1775,9 @@ public:
|
|||
|
||||
// Pure C# interfaces
|
||||
const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
|
||||
if (*Char(interface_list) && *Char(pure_interfaces))
|
||||
Append(interface_list, ", ");
|
||||
Append(interface_list, pure_interfaces);
|
||||
// Start writing the proxy class
|
||||
if (!has_outerclass)
|
||||
Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
|
||||
|
|
@ -1725,8 +1790,8 @@ public:
|
|||
|
||||
Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
|
||||
" $csclassname", // Class name and base class
|
||||
(*Char(wanted_base) || *Char(pure_interfaces)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(pure_interfaces)) ? // Interfaces
|
||||
", " : "", pure_interfaces, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
|
||||
(*Char(wanted_base) || *Char(interface_list)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(interface_list)) ? // Interfaces
|
||||
", " : "", interface_list, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) : // main body of class
|
||||
typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF), // main body of class
|
||||
NIL);
|
||||
|
||||
|
|
@ -1771,6 +1836,8 @@ public:
|
|||
Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n",
|
||||
NIL);
|
||||
}
|
||||
if (*Char(interface_upcasts))
|
||||
Printv(proxy_class_def, interface_upcasts, NIL);
|
||||
|
||||
if (feature_director) {
|
||||
// Generate director connect method
|
||||
|
|
@ -1852,6 +1919,8 @@ public:
|
|||
Delete(director_connect_method_name);
|
||||
}
|
||||
|
||||
Delete(interface_upcasts);
|
||||
Delete(interface_list);
|
||||
Delete(attributes);
|
||||
Delete(destruct);
|
||||
|
||||
|
|
@ -1899,12 +1968,40 @@ public:
|
|||
Delete(baseclass);
|
||||
}
|
||||
|
||||
void emitInterfaceDeclaration(Node *n, String *iname, File *f_interface) {
|
||||
Printv(f_interface, typemapLookup(n, "csimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
|
||||
Printf(f_interface, "public interface %s", iname);
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
String *bases = 0;
|
||||
for (Iterator base = First(baselist); base.item; base = Next(base)) {
|
||||
if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface"))
|
||||
continue; // TODO: warn about skipped non-interface bases
|
||||
String *base_iname = Getattr(base.item, "feature:interface:name");
|
||||
if (!bases)
|
||||
bases = NewStringf(" : %s", base_iname);
|
||||
else {
|
||||
Append(bases, ", ");
|
||||
Append(bases, base_iname);
|
||||
}
|
||||
}
|
||||
if (bases) {
|
||||
Printv(f_interface, bases, NIL);
|
||||
Delete(bases);
|
||||
}
|
||||
}
|
||||
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, " HandleRef %s();\n", cptr_func);
|
||||
else
|
||||
Printf(f_interface, " HandleRef SWIGInterfaceUpcast();\n");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* classHandler()
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
virtual int classHandler(Node *n) {
|
||||
|
||||
String *nspace = getNSpace();
|
||||
File *f_proxy = NULL;
|
||||
// save class local variables
|
||||
|
|
@ -1915,6 +2012,9 @@ 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) {
|
||||
proxy_class_name = NewString(Getattr(n, "sym:name"));
|
||||
|
|
@ -1963,10 +2063,36 @@ public:
|
|||
}
|
||||
else
|
||||
++nesting_depth;
|
||||
proxy_class_def = NewString("");
|
||||
proxy_class_code = NewString("");
|
||||
destructor_call = NewString("");
|
||||
proxy_class_constants_code = NewString("");
|
||||
|
||||
// Start writing out the proxy class file
|
||||
emitBanner(f_proxy);
|
||||
addOpenNamespace(nspace, f_proxy);
|
||||
|
||||
Clear(proxy_class_def);
|
||||
Clear(proxy_class_code);
|
||||
|
||||
destructor_call = NewStringEmpty();
|
||||
proxy_class_constants_code = NewStringEmpty();
|
||||
Swig_propagate_interface_methods(n);
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
interface_class_code = NewStringEmpty();
|
||||
String *iname = Getattr(n, "feature:interface:name");
|
||||
if (!iname) {
|
||||
Swig_error(Getfile(n), Getline(n), "Interface %s has no name attribute", proxy_class_name);
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
filen = NewStringf("%s%s.cs", output_directory, iname);
|
||||
f_interface = NewFile(filen, "w", SWIG_output_files());
|
||||
if (!f_interface) {
|
||||
FileErrorDisplay(filen);
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
Append(filenames_list, filen); // file name ownership goes to the list
|
||||
emitBanner(f_interface);
|
||||
addOpenNamespace(nspace, f_interface);
|
||||
emitInterfaceDeclaration(n, iname, f_interface);
|
||||
}
|
||||
Delete(output_directory);
|
||||
}
|
||||
|
||||
Language::classHandler(n);
|
||||
|
|
@ -2056,10 +2182,17 @@ public:
|
|||
Delete(norm_name);
|
||||
Delete(wname);
|
||||
Delete(downcast_method);
|
||||
|
||||
if (f_interface) {
|
||||
Printv(f_interface, interface_class_code, "}\n", NIL);
|
||||
addCloseNamespace(nspace, f_interface);
|
||||
Delete(f_interface);
|
||||
}
|
||||
|
||||
emitDirectorExtraMethods(n);
|
||||
|
||||
Delete(interface_class_code);
|
||||
interface_class_code = old_interface_class_code;
|
||||
Delete(csclazzname);
|
||||
Delete(proxy_class_name);
|
||||
proxy_class_name = old_proxy_class_name;
|
||||
|
|
@ -2145,6 +2278,8 @@ public:
|
|||
String *pre_code = NewString("");
|
||||
String *post_code = NewString("");
|
||||
String *terminator_code = NewString("");
|
||||
bool is_interface = Getattr(parentNode(n), "feature:interface") != 0
|
||||
&& !static_flag && Getattr(n, "interface:owner") == 0;
|
||||
|
||||
if (!proxy_flag)
|
||||
return;
|
||||
|
|
@ -2217,8 +2352,10 @@ public:
|
|||
Printf(function_code, " %s ", methodmods);
|
||||
if (!is_smart_pointer()) {
|
||||
// Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
|
||||
if (Getattr(n, "override"))
|
||||
Printf(function_code, "override ");
|
||||
if (Node *base = Getattr(n, "override")) {
|
||||
if (!Getattr(parentNode(base), "feature:interface"))
|
||||
Printf(function_code, "override ");
|
||||
}
|
||||
else if (checkAttribute(n, "storage", "virtual"))
|
||||
Printf(function_code, "virtual ");
|
||||
if (Getattr(n, "hides"))
|
||||
|
|
@ -2228,6 +2365,9 @@ public:
|
|||
if (static_flag)
|
||||
Printf(function_code, "static ");
|
||||
Printf(function_code, "%s %s(", return_type, proxy_function_name);
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
|
||||
|
||||
|
||||
Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
|
||||
if (!static_flag)
|
||||
|
|
@ -2307,10 +2447,15 @@ public:
|
|||
}
|
||||
|
||||
/* Add parameter to proxy function */
|
||||
if (gencomma >= 2)
|
||||
if (gencomma >= 2) {
|
||||
Printf(function_code, ", ");
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, ", ");
|
||||
}
|
||||
gencomma = 2;
|
||||
Printf(function_code, "%s %s", param_type, arg);
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, "%s %s", param_type, arg);
|
||||
|
||||
Delete(arg);
|
||||
Delete(param_type);
|
||||
|
|
@ -2320,6 +2465,8 @@ public:
|
|||
|
||||
Printf(imcall, ")");
|
||||
Printf(function_code, ")");
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, ");\n");
|
||||
|
||||
// Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
|
||||
if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
/* Hash type used for upcalls from C/C++ */
|
||||
typedef DOH UpcallData;
|
||||
// helper function used in feature:interface implementation
|
||||
void Swig_propagate_interface_methods(Node *n);
|
||||
|
||||
class JAVA:public Language {
|
||||
static const char *usage;
|
||||
|
|
@ -53,6 +55,7 @@ class JAVA:public Language {
|
|||
String *imclass_class_code; // intermediary class code
|
||||
String *proxy_class_def;
|
||||
String *proxy_class_code;
|
||||
String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
|
||||
String *module_class_code;
|
||||
String *proxy_class_name; // proxy class name
|
||||
String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name
|
||||
|
|
@ -125,6 +128,7 @@ public:
|
|||
imclass_class_code(NULL),
|
||||
proxy_class_def(NULL),
|
||||
proxy_class_code(NULL),
|
||||
interface_class_code(NULL),
|
||||
module_class_code(NULL),
|
||||
proxy_class_name(NULL),
|
||||
full_proxy_class_name(NULL),
|
||||
|
|
@ -1288,8 +1292,10 @@ public:
|
|||
// Add extra indentation
|
||||
Replaceall(enum_code, "\n", "\n ");
|
||||
Replaceall(enum_code, " \n", "\n");
|
||||
|
||||
Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
|
||||
if (GetFlag(getCurrentClass(), "feature:interface"))
|
||||
Printv(interface_class_code, " ", enum_code, "\n\n", NIL);
|
||||
else
|
||||
Printv(proxy_class_constants_code, " ", enum_code, "\n\n", NIL);
|
||||
} else {
|
||||
// Global enums are defined in their own file
|
||||
String *output_directory = outputDirectory(nspace);
|
||||
|
|
@ -1723,6 +1729,71 @@ public:
|
|||
return Language::pragmaDirective(n);
|
||||
}
|
||||
|
||||
String *getQualifiedInterfaceName(Node *n) {
|
||||
String *ret = Getattr(n, "interface:qname");
|
||||
if (!ret) {
|
||||
String *nspace = Getattr(n, "sym:nspace");
|
||||
String *symname = Getattr(n, "feature:interface:name");
|
||||
if (nspace) {
|
||||
if (package)
|
||||
ret = NewStringf("%s.%s.%s", package, nspace, symname);
|
||||
else
|
||||
ret = NewStringf("%s.%s", nspace, symname);
|
||||
} else {
|
||||
if (package)
|
||||
ret = NewStringf("%s.%s", package, symname);
|
||||
else
|
||||
ret = Copy(symname);
|
||||
}
|
||||
Setattr(n, "interface:qname", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
String *c_baseclass = SwigType_namestr(Getattr(base, "name"));
|
||||
String *iname = Getattr(base, "feature:interface:name");
|
||||
if (Len(interface_list))
|
||||
Append(interface_list, ", ");
|
||||
Append(interface_list, iname);
|
||||
|
||||
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", iname);
|
||||
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);
|
||||
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);
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
|
||||
" jlong baseptr = 0;\n"
|
||||
" (void)jenv;\n"
|
||||
" (void)jcls;\n"
|
||||
" *(", c_baseclass, " **)&baseptr = *(", c_classname, " **)&jarg1;\n"
|
||||
" return baseptr;\n"
|
||||
"}\n", "\n", NIL);
|
||||
Delete(upcast_name);
|
||||
Delete(wname);
|
||||
Delete(jniname);
|
||||
Delete(upcast_method);
|
||||
Delete(c_baseclass);
|
||||
}
|
||||
// Printf(stdout, " => %s\n", interface_list);
|
||||
Delete(keys);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitProxyClassDefAndCPPCasts()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
@ -1732,6 +1803,8 @@ public:
|
|||
String *c_baseclass = NULL;
|
||||
String *baseclass = NULL;
|
||||
String *c_baseclassname = NULL;
|
||||
String *interface_list = NewStringEmpty();
|
||||
String *interface_upcasts = NewStringEmpty();
|
||||
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
|
||||
bool feature_director = Swig_directorclass(n) ? true : false;
|
||||
bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
|
||||
|
|
@ -1748,9 +1821,8 @@ public:
|
|||
List *baselist = Getattr(n, "bases");
|
||||
if (baselist) {
|
||||
Iterator base = First(baselist);
|
||||
while (base.item && GetFlag(base.item, "feature:ignore")) {
|
||||
while (base.item && (GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface")))
|
||||
base = Next(base);
|
||||
}
|
||||
if (base.item) {
|
||||
c_baseclassname = Getattr(base.item, "name");
|
||||
baseclass = Copy(getProxyName(c_baseclassname));
|
||||
|
|
@ -1759,20 +1831,22 @@ public:
|
|||
base = Next(base);
|
||||
/* Warn about multiple inheritance for additional base class(es) */
|
||||
while (base.item) {
|
||||
if (GetFlag(base.item, "feature:ignore")) {
|
||||
base = Next(base);
|
||||
continue;
|
||||
}
|
||||
String *proxyclassname = Getattr(n, "classtypeobj");
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
Swig_warning(WARN_JAVA_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));
|
||||
if (!GetFlag(base.item, "feature:ignore") && !Getattr(base.item, "feature:interface")) {
|
||||
String *proxyclassname = Getattr(n, "classtypeobj");
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
Swig_warning(WARN_JAVA_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));
|
||||
}
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hash *interface_bases = Getattr(n, "interface:bases");
|
||||
if (interface_bases)
|
||||
addInterfaceNameAndUpcasts(interface_list, interface_upcasts, interface_bases, c_classname);
|
||||
|
||||
bool derived = baseclass && getProxyName(c_baseclassname);
|
||||
if (derived && purebase_notderived)
|
||||
pure_baseclass = empty_string;
|
||||
|
|
@ -1793,7 +1867,9 @@ public:
|
|||
|
||||
// Pure Java interfaces
|
||||
const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
|
||||
|
||||
if (*Char(interface_list) && *Char(pure_interfaces))
|
||||
Append(interface_list, ", ");
|
||||
Append(interface_list, pure_interfaces);
|
||||
// Start writing the proxy class
|
||||
if (!has_outerclass) // Import statements
|
||||
Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL);
|
||||
|
|
@ -1801,8 +1877,8 @@ public:
|
|||
Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes
|
||||
Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
|
||||
" $javaclassname", // Class name and bases
|
||||
(*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(pure_interfaces) ? // Pure Java interfaces
|
||||
" implements " : "", pure_interfaces, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class
|
||||
(*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(interface_list) ? // Pure Java interfaces
|
||||
" implements " : "", interface_list, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) : // main body of class
|
||||
typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
|
||||
NIL);
|
||||
|
||||
|
|
@ -1845,6 +1921,8 @@ public:
|
|||
if (*Char(destruct))
|
||||
Printv(proxy_class_def, "\n ", destruct_methodmodifiers, " void ", destruct_methodname, "()", destructor_throws_clause, " ", destruct, "\n", NIL);
|
||||
}
|
||||
if (*Char(interface_upcasts))
|
||||
Printv(proxy_class_def, interface_upcasts, NIL);
|
||||
|
||||
/* Insert directordisconnect typemap, if this class has directors enabled */
|
||||
/* Also insert the swigTakeOwnership and swigReleaseOwnership methods */
|
||||
|
|
@ -1866,6 +1944,8 @@ public:
|
|||
Delete(take_jnicall);
|
||||
}
|
||||
|
||||
Delete(interface_upcasts);
|
||||
Delete(interface_list);
|
||||
Delete(attributes);
|
||||
Delete(destruct);
|
||||
|
||||
|
|
@ -1920,12 +2000,48 @@ public:
|
|||
Delete(baseclass);
|
||||
}
|
||||
|
||||
void emitInterfaceDeclaration(Node *n, String *iname, File *f_interface, String *nspace) {
|
||||
if (package || nspace) {
|
||||
Printf(f_interface, "package ");
|
||||
if (package)
|
||||
Printv(f_interface, package, nspace ? "." : "", NIL);
|
||||
if (nspace)
|
||||
Printv(f_interface, nspace, NIL);
|
||||
Printf(f_interface, ";\n");
|
||||
}
|
||||
|
||||
Printv(f_interface, typemapLookup(n, "javaimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
|
||||
Printf(f_interface, "public interface %s", iname);
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
String *bases = 0;
|
||||
for (Iterator base = First(baselist); base.item; base = Next(base)) {
|
||||
if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface"))
|
||||
continue; // TODO: warn about skipped non-interface bases
|
||||
String *base_iname = Getattr(base.item, "feature:interface:name");
|
||||
if (!bases)
|
||||
bases = Copy(base_iname);
|
||||
else {
|
||||
Append(bases, ", ");
|
||||
Append(bases, base_iname);
|
||||
}
|
||||
}
|
||||
if (bases) {
|
||||
Printv(f_interface, " extends ", bases, NIL);
|
||||
Delete(bases);
|
||||
}
|
||||
}
|
||||
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", iname);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* classHandler()
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
virtual int classHandler(Node *n) {
|
||||
|
||||
File *f_proxy = NULL;
|
||||
String *old_proxy_class_name = proxy_class_name;
|
||||
String *old_full_proxy_class_name = full_proxy_class_name;
|
||||
|
|
@ -1936,6 +2052,8 @@ 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;
|
||||
interface_class_code = 0;
|
||||
|
||||
if (proxy_flag) {
|
||||
proxy_class_name = NewString(Getattr(n, "sym:name"));
|
||||
|
|
@ -2022,7 +2140,28 @@ public:
|
|||
destructor_call = NewString("");
|
||||
destructor_throws_clause = NewString("");
|
||||
proxy_class_constants_code = NewString("");
|
||||
|
||||
Swig_propagate_interface_methods(n);
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
interface_class_code = NewStringEmpty();
|
||||
String *iname = Getattr(n, "feature:interface:name");
|
||||
if (!iname) {
|
||||
Swig_error(Getfile(n), Getline(n), "Interface %s has no name attribute", proxy_class_name);
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
filen = NewStringf("%s%s.java", output_directory, iname);
|
||||
f_interface = NewFile(filen, "w", SWIG_output_files());
|
||||
if (!f_interface) {
|
||||
FileErrorDisplay(filen);
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
Append(filenames_list, filen); // file name ownership goes to the list
|
||||
emitBanner(f_interface);
|
||||
emitInterfaceDeclaration(n, iname, f_interface, nspace);
|
||||
}
|
||||
Delete(output_directory);
|
||||
}
|
||||
|
||||
Language::classHandler(n);
|
||||
|
||||
if (proxy_flag) {
|
||||
|
|
@ -2110,6 +2249,11 @@ public:
|
|||
Delete(downcast_method);
|
||||
}
|
||||
|
||||
if (f_interface) {
|
||||
Printv(f_interface, interface_class_code, "}\n", NIL);
|
||||
Delete(f_interface);
|
||||
}
|
||||
|
||||
emitDirectorExtraMethods(n);
|
||||
|
||||
Delete(javaclazzname);
|
||||
|
|
@ -2203,6 +2347,8 @@ public:
|
|||
bool setter_flag = false;
|
||||
String *pre_code = NewString("");
|
||||
String *post_code = NewString("");
|
||||
bool is_interface = Getattr(parentNode(n), "feature:interface") != 0
|
||||
&& !static_flag && Getattr(n, "interface:owner") == 0;
|
||||
|
||||
if (!proxy_flag)
|
||||
return;
|
||||
|
|
@ -2252,6 +2398,9 @@ public:
|
|||
if (static_flag)
|
||||
Printf(function_code, "static ");
|
||||
Printf(function_code, "%s %s(", return_type, proxy_function_name);
|
||||
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, " %s %s(", return_type, proxy_function_name);
|
||||
|
||||
Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
|
||||
if (!static_flag) {
|
||||
|
|
@ -2339,10 +2488,15 @@ public:
|
|||
}
|
||||
|
||||
/* Add parameter to proxy function */
|
||||
if (gencomma >= 2)
|
||||
if (gencomma >= 2) {
|
||||
Printf(function_code, ", ");
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, ", ");
|
||||
}
|
||||
gencomma = 2;
|
||||
Printf(function_code, "%s %s", param_type, arg);
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, "%s %s", param_type, arg);
|
||||
|
||||
if (prematureGarbageCollectionPreventionParameter(pt, p)) {
|
||||
String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
|
||||
|
|
@ -2364,6 +2518,8 @@ public:
|
|||
|
||||
Printf(imcall, ")");
|
||||
Printf(function_code, ")");
|
||||
if (is_interface)
|
||||
Printf(interface_class_code, ");\n");
|
||||
|
||||
// Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
|
||||
if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
|
||||
|
|
|
|||
|
|
@ -3816,3 +3816,104 @@ Language *Language::instance() {
|
|||
Hash *Language::getClassHash() const {
|
||||
return classhash;
|
||||
}
|
||||
|
||||
// 4 methods below are used in C# && Java module "feature:interface" implementation
|
||||
//
|
||||
// Collect all not abstract methods from the bases marked as "interface"
|
||||
static void collect_interface_methods(Node *n, List *methods) {
|
||||
if (Hash *bases = Getattr(n, "interface:bases")){
|
||||
List *keys = Keys(bases);
|
||||
for (Iterator base = First(keys); base.item; base = Next(base)) {
|
||||
Node *cls = Getattr(bases, base.item);
|
||||
if (cls == n)
|
||||
continue;
|
||||
for (Node *child = firstChild(cls); child; child = nextSibling(child)) {
|
||||
if (strcmp(Char(nodeType(child)), "cdecl") == 0) {
|
||||
if (GetFlag(child, "feature:ignore") || Getattr(child, "interface:owner"))
|
||||
continue; // skip methods propagated to bases
|
||||
Node *m = Copy(child);
|
||||
set_nextSibling(m, NIL);
|
||||
set_previousSibling(m, NIL);
|
||||
Setattr(m, "interface:owner", cls);
|
||||
Append(methods, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete(keys);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_bases
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void collect_interface_bases(Hash *bases, Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
String *name = Getattr(n, "feature:interface:name");
|
||||
if (!Getattr(bases, name))
|
||||
Setattr(bases, name, n);
|
||||
}
|
||||
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
for (Iterator base = First(baselist); base.item; base = Next(base)) {
|
||||
if (!GetFlag(base.item, "feature:ignore")) {
|
||||
if (Getattr(base.item, "feature:interface"))
|
||||
collect_interface_bases(bases, base.item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_and_set_interface_bases()
|
||||
*
|
||||
* Create a hash containing all the classes up the inheritance hierarchy
|
||||
* marked with feature:interface (including this class n).
|
||||
* Stops going up the inheritance chain as soon as a class is found without
|
||||
* feature:interface.
|
||||
* The idea is to find all the base interfaces that a class must implement.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void collect_and_set_interface_bases(Node *n) {
|
||||
Hash *interface_bases = NewHash();
|
||||
collect_interface_bases(interface_bases, n);
|
||||
if (Len(interface_bases) == 0)
|
||||
Delete(interface_bases);
|
||||
else
|
||||
Setattr(n, "interface:bases", interface_bases);
|
||||
}
|
||||
|
||||
// Append all the interface methods not implemented in the current class, so that it would not be abstract
|
||||
void Swig_propagate_interface_methods(Node *n) {
|
||||
collect_and_set_interface_bases(n);
|
||||
List *methods = NewList();
|
||||
collect_interface_methods(n, methods);
|
||||
bool is_interface = Getattr(n, "feature:interface") != 0;
|
||||
for (Iterator mi = First(methods); mi.item; mi = Next(mi)) {
|
||||
if (!is_interface && GetFlag(mi.item, "abstract"))
|
||||
continue;
|
||||
String *this_decl = Getattr(mi.item, "decl");
|
||||
String *resolved_decl = SwigType_typedef_resolve_all(this_decl);
|
||||
bool overloaded = false;
|
||||
if (SwigType_isfunction(resolved_decl)) {
|
||||
String *name = Getattr(mi.item, "name");
|
||||
for (Node *child = firstChild(n); child; child = nextSibling(child)) {
|
||||
if (Getattr(child, "interface:owner"))
|
||||
break; // at the end of the list are newly appended methods
|
||||
if (checkAttribute(child, "name", name)) {
|
||||
String *decl = SwigType_typedef_resolve_all(Getattr(child, "decl"));
|
||||
overloaded = Strcmp(decl, this_decl) == 0;
|
||||
Delete(decl);
|
||||
if (overloaded)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete(resolved_decl);
|
||||
if (!overloaded)
|
||||
appendChild(n, mi.item);
|
||||
else
|
||||
Delete(mi.item);
|
||||
}
|
||||
Delete(methods);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue