Merge branch 'interfaces'
* interfaces: Documentation and CHANGES entry for interface feature interface macro argument name tweaks Change the name of the interface in %feature to be more portable Interface feature fix for typedef types Add limited support for %interface_impl and %shared_ptr Multiple inheritance warning wording tweak C# "override" fix for "extend" case Add checks for interface name symbol clashes interface feature test changes for the tests to pass for all languages Rename feature_interface.i to swiginterface.i Re-organization of the interface feature common code Port Java interface tests to C# Test %interface Test %interface_impl Use rstrip instead of regex encoder in %feature_rename Add rstrip encoder for use in %rename. Interface macros: %interface %interface_impl %interface_custom Add $interfacename family of special variable expansions Add multiple_inheritance_nspace testcase Interface name handling improvements and special variable changes Correct regex example comment Properly hide unexposed naming functions in naming.c C++ namespace testing for interface feature interface feature - SWIG_JAVABODY_PROXY does not need to be overridden Support namespaces and nspace with the interface feature for C# Support namespaces and nspace with the interface feature for Java Cosmetic test case changes Add Java premature garbage collection prevention parameter (pgcpp) to interface feature Create javainterfacecode and csinterfacecode typemaps IntPtr & HandleRef absolute names used virtual/override fix Improve interface feature checks Add another interface test selecting just one base as an interface Comments added to interface feature implementation and cosmetic code changes Add overloading tests for interface feature Refactor multiple inheritance warnings director generation fixes interface feature updates for C# latest on master interfaces branch merge fixes 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: CHANGES.current
This commit is contained in:
commit
0f0345c214
39 changed files with 4624 additions and 255 deletions
|
|
@ -729,6 +729,8 @@ Allocate():
|
|||
}
|
||||
}
|
||||
|
||||
Swig_interface_propagate_methods(n);
|
||||
|
||||
/* Only care about default behavior. Remove temporary values */
|
||||
Setattr(n, "allocate:visit", "1");
|
||||
Swig_symbol_setscope(symtab);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,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 +127,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),
|
||||
|
|
@ -272,6 +274,7 @@ public:
|
|||
SWIG_config_file("csharp.swg");
|
||||
|
||||
allow_overloading();
|
||||
Swig_interface_feature_enable();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
|
@ -1643,6 +1646,119 @@ public:
|
|||
return Language::pragmaDirective(n);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* getQualifiedInterfaceName()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *getQualifiedInterfaceName(Node *n) {
|
||||
String *ret = Getattr(n, "interface:qname");
|
||||
if (!ret) {
|
||||
String *nspace = Getattr(n, "sym:nspace");
|
||||
String *interface_name = Getattr(n, "interface:name");
|
||||
if (nspace) {
|
||||
if (namespce)
|
||||
ret = NewStringf("%s.%s.%s", namespce, nspace, interface_name);
|
||||
else
|
||||
ret = NewStringf("%s.%s", nspace, interface_name);
|
||||
} else {
|
||||
ret = Copy(interface_name);
|
||||
}
|
||||
Setattr(n, "interface:qname", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* getInterfaceName()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *getInterfaceName(SwigType *t, bool qualified) {
|
||||
String *interface_name = NULL;
|
||||
if (proxy_flag) {
|
||||
Node *n = classLookup(t);
|
||||
if (n && Getattr(n, "interface:name"))
|
||||
interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
|
||||
}
|
||||
return interface_name;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* addInterfaceNameAndUpcasts()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void addInterfaceNameAndUpcasts(SwigType *smart, 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 *interface_name = Getattr(base, "interface:name");
|
||||
if (Len(interface_list))
|
||||
Append(interface_list, ", ");
|
||||
Append(interface_list, interface_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 = NewStringf("%s_GetInterfaceCPtr", interface_name);
|
||||
Replaceall(cptr_method_name, ".", "_");
|
||||
Replaceall(cptr_method_name, "$interfacename", interface_name);
|
||||
|
||||
String *upcast_method_name = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name);
|
||||
upcastsCode(smart, upcast_method_name, c_classname, c_baseclass);
|
||||
|
||||
Delete(upcast_method_name);
|
||||
Delete(cptr_method_name);
|
||||
Delete(interface_code);
|
||||
Delete(c_baseclass);
|
||||
}
|
||||
Delete(keys);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* upcastsCode()
|
||||
*
|
||||
* Add code for C++ casting to base class
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void upcastsCode(SwigType *smart, String *upcast_method_name, String *c_classname, String *c_baseclass) {
|
||||
String *wname = Swig_name_wrapper(upcast_method_name);
|
||||
|
||||
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_name);
|
||||
|
||||
Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
|
||||
|
||||
if (smart) {
|
||||
SwigType *bsmart = Copy(smart);
|
||||
SwigType *rclassname = SwigType_typedef_resolve_all(c_classname);
|
||||
SwigType *rbaseclass = SwigType_typedef_resolve_all(c_baseclass);
|
||||
Replaceall(bsmart, rclassname, rbaseclass);
|
||||
Delete(rclassname);
|
||||
Delete(rbaseclass);
|
||||
String *smartnamestr = SwigType_namestr(smart);
|
||||
String *bsmartnamestr = SwigType_namestr(bsmart);
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n",
|
||||
" return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n"
|
||||
"}\n", "\n", NIL);
|
||||
Delete(bsmartnamestr);
|
||||
Delete(smartnamestr);
|
||||
Delete(bsmart);
|
||||
} else {
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT ", c_baseclass, " * SWIGSTDCALL ", wname, "(", c_classname, " *jarg1) {\n",
|
||||
" return (", c_baseclass, " *)jarg1;\n"
|
||||
"}\n", "\n", NIL);
|
||||
}
|
||||
Delete(wname);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitProxyClassDefAndCPPCasts()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
@ -1652,9 +1768,12 @@ 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");
|
||||
SwigType *smart = Swig_cparse_smartptr(n);
|
||||
|
||||
// Inheritance from pure C# classes
|
||||
Node *attributes = NewHash();
|
||||
|
|
@ -1667,31 +1786,29 @@ public:
|
|||
if (!purebase_replace) {
|
||||
List *baselist = Getattr(n, "bases");
|
||||
if (baselist) {
|
||||
Iterator base = First(baselist);
|
||||
while (base.item && GetFlag(base.item, "feature:ignore")) {
|
||||
base = Next(base);
|
||||
}
|
||||
if (base.item) {
|
||||
c_baseclassname = Getattr(base.item, "name");
|
||||
baseclass = Copy(getProxyName(c_baseclassname));
|
||||
if (baseclass)
|
||||
c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
|
||||
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));
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
Iterator base = First(baselist);
|
||||
while (base.item) {
|
||||
if (!(GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) {
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
if (!c_baseclassname) {
|
||||
c_baseclassname = baseclassname;
|
||||
baseclass = Copy(getProxyName(baseclassname));
|
||||
if (baseclass)
|
||||
c_baseclass = SwigType_namestr(baseclassname);
|
||||
} else {
|
||||
/* 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, base %s ignored. Multiple inheritance is not supported in C#.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
|
||||
}
|
||||
}
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
}
|
||||
Hash *interface_bases = Getattr(n, "interface:bases");
|
||||
if (interface_bases)
|
||||
addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
|
||||
|
||||
bool derived = baseclass && getProxyName(c_baseclassname);
|
||||
if (derived && purebase_notderived)
|
||||
|
|
@ -1707,12 +1824,15 @@ public:
|
|||
Swig_error(Getfile(n), Getline(n), "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
|
||||
} else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
|
||||
Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#. "
|
||||
"Warning for %s, base %s ignored. Multiple inheritance is not supported in C#. "
|
||||
"Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
|
||||
}
|
||||
|
||||
// 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 +1845,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 +1891,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 +1974,8 @@ public:
|
|||
Delete(director_connect_method_name);
|
||||
}
|
||||
|
||||
Delete(interface_upcasts);
|
||||
Delete(interface_list);
|
||||
Delete(attributes);
|
||||
Delete(destruct);
|
||||
|
||||
|
|
@ -1859,54 +1983,92 @@ public:
|
|||
Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE), // extra C# code
|
||||
"\n", NIL);
|
||||
|
||||
// Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
|
||||
if (derived) {
|
||||
SwigType *smart = Swig_cparse_smartptr(n);
|
||||
String *upcast_method = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
|
||||
String *wname = Swig_name_wrapper(upcast_method);
|
||||
|
||||
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);
|
||||
|
||||
if (smart) {
|
||||
SwigType *bsmart = Copy(smart);
|
||||
SwigType *rclassname = SwigType_typedef_resolve_all(c_classname);
|
||||
SwigType *rbaseclass = SwigType_typedef_resolve_all(c_baseclass);
|
||||
Replaceall(bsmart, rclassname, rbaseclass);
|
||||
Delete(rclassname);
|
||||
Delete(rbaseclass);
|
||||
String *smartnamestr = SwigType_namestr(smart);
|
||||
String *bsmartnamestr = SwigType_namestr(bsmart);
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT ", bsmartnamestr, " * SWIGSTDCALL ", wname, "(", smartnamestr, " *jarg1) {\n",
|
||||
" return jarg1 ? new ", bsmartnamestr, "(*jarg1) : 0;\n"
|
||||
"}\n", "\n", NIL);
|
||||
Delete(bsmartnamestr);
|
||||
Delete(smartnamestr);
|
||||
Delete(bsmart);
|
||||
} else {
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT ", c_baseclass, " * SWIGSTDCALL ", wname, "(", c_classname, " *jarg1) {\n",
|
||||
" return (", c_baseclass, " *)jarg1;\n"
|
||||
"}\n", "\n", NIL);
|
||||
}
|
||||
Delete(wname);
|
||||
Delete(upcast_method);
|
||||
Delete(smart);
|
||||
String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
|
||||
upcastsCode(smart, upcast_method_name, c_classname, c_baseclass);
|
||||
Delete(upcast_method_name);
|
||||
}
|
||||
|
||||
Delete(smart);
|
||||
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);
|
||||
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, "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");
|
||||
|
||||
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
|
||||
Node *attributes = NewHash();
|
||||
SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
|
||||
const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
|
||||
bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
|
||||
bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
|
||||
Delete(attributes);
|
||||
if (!purebase_replace) {
|
||||
if (List *baselist = Getattr(n, "bases")) {
|
||||
Iterator base = First(baselist);
|
||||
while (base.item && (GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface")))
|
||||
base = Next(base);
|
||||
direct_base = base.item;
|
||||
}
|
||||
if (!direct_base && purebase_notderived)
|
||||
direct_base = symbolLookup(const_cast<String*>(pure_baseclass));
|
||||
} else {
|
||||
direct_base = symbolLookup(const_cast<String*>(pure_baseclass));
|
||||
}
|
||||
Setattr(n, "direct_base", direct_base);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* classHandler()
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
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;
|
||||
|
|
@ -1915,9 +2077,12 @@ 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");
|
||||
String *old_interface_class_code = interface_class_code;
|
||||
interface_class_code = 0;
|
||||
|
||||
if (proxy_flag) {
|
||||
proxy_class_name = NewString(Getattr(n, "sym:name"));
|
||||
String *interface_name = Getattr(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
|
||||
if (Node *outer = Getattr(n, "nested:outer")) {
|
||||
String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
|
||||
for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
|
||||
|
|
@ -1927,13 +2092,16 @@ public:
|
|||
String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
|
||||
if (!addSymbol(proxy_class_name, n, fnspace))
|
||||
return SWIG_ERROR;
|
||||
if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
|
||||
return SWIG_ERROR;
|
||||
if (nspace)
|
||||
Delete(fnspace);
|
||||
Delete(outerClassesPrefix);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (!addSymbol(proxy_class_name, n, nspace))
|
||||
return SWIG_ERROR;
|
||||
if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
|
||||
if (!nspace) {
|
||||
|
|
@ -1960,13 +2128,25 @@ public:
|
|||
f_proxy = getOutputFile(output_directory, proxy_class_name);
|
||||
|
||||
addOpenNamespace(nspace, f_proxy);
|
||||
Delete(output_directory);
|
||||
}
|
||||
else
|
||||
++nesting_depth;
|
||||
|
||||
proxy_class_def = NewString("");
|
||||
proxy_class_code = NewString("");
|
||||
destructor_call = NewString("");
|
||||
proxy_class_constants_code = NewString("");
|
||||
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
interface_class_code = NewString("");
|
||||
String *output_directory = outputDirectory(nspace);
|
||||
f_interface = getOutputFile(output_directory, interface_name);
|
||||
addOpenNamespace(nspace, f_interface);
|
||||
emitInterfaceDeclaration(n, interface_name, interface_class_code);
|
||||
Delete(output_directory);
|
||||
}
|
||||
calculateDirectBase(n);
|
||||
}
|
||||
|
||||
Language::classHandler(n);
|
||||
|
|
@ -1980,22 +2160,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 {
|
||||
|
|
@ -2058,8 +2244,18 @@ public:
|
|||
Delete(downcast_method);
|
||||
}
|
||||
|
||||
if (f_interface) {
|
||||
Printv(f_interface, interface_class_code, "}\n", NIL);
|
||||
addCloseNamespace(nspace, f_interface);
|
||||
if (f_interface != f_single_out)
|
||||
Delete(f_interface);
|
||||
f_interface = 0;
|
||||
}
|
||||
|
||||
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 +2341,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 +2415,21 @@ 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_ovr = Getattr(n, "override")) {
|
||||
if (GetFlag(n, "isextendmember"))
|
||||
Printf(function_code, "override ");
|
||||
else {
|
||||
Node* base = parentNode(base_ovr);
|
||||
bool ovr = false;
|
||||
for (Node* direct_base = Getattr(parentNode(n), "direct_base"); direct_base; direct_base = Getattr(direct_base, "direct_base")) {
|
||||
if (direct_base == base) { // "override" only applies if the base was not discarded (e.g. in case of multiple inheritance or via "ignore")
|
||||
ovr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Printf(function_code, ovr ? "override " : "virtual ");
|
||||
}
|
||||
}
|
||||
else if (checkAttribute(n, "storage", "virtual"))
|
||||
Printf(function_code, "virtual ");
|
||||
if (Getattr(n, "hides"))
|
||||
|
|
@ -2228,6 +2439,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 +2521,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 +2539,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))) {
|
||||
|
|
@ -3188,6 +3409,50 @@ public:
|
|||
substitution_performed = true;
|
||||
Delete(classnametype);
|
||||
}
|
||||
if (Strstr(tm, "$csinterfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$csinterfacename", true);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$*csinterfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
Delete(SwigType_pop(interfacenametype));
|
||||
if (Len(interfacenametype) > 0) {
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*csinterfacename", true);
|
||||
substitution_performed = true;
|
||||
}
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$&csinterfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
SwigType_add_pointer(interfacenametype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&csinterfacename", true);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$interfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", false);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$*interfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
Delete(SwigType_pop(interfacenametype));
|
||||
if (Len(interfacenametype) > 0) {
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", false);
|
||||
substitution_performed = true;
|
||||
}
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$&interfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
SwigType_add_pointer(interfacenametype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", false);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
|
||||
Delete(strippedtype);
|
||||
Delete(type);
|
||||
|
|
@ -3233,6 +3498,20 @@ public:
|
|||
Delete(replacementname);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* substituteInterfacenameSpecialVariable()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool qualified) {
|
||||
|
||||
String *interfacename = getInterfaceName(interfacenametype, qualified);
|
||||
if (interfacename) {
|
||||
String *replacementname = Copy(interfacename);
|
||||
Replaceall(tm, interfacenamespecialvariable, replacementname);
|
||||
Delete(replacementname);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitTypeWrapperClass()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
|
|||
|
|
@ -3123,28 +3123,23 @@ private:
|
|||
List *baselist = Getattr(n, "bases");
|
||||
if (baselist) {
|
||||
Iterator base = First(baselist);
|
||||
while (base.item && GetFlag(base.item, "feature:ignore")) {
|
||||
base = Next(base);
|
||||
}
|
||||
if (base.item) {
|
||||
basenode = base.item;
|
||||
c_baseclassname = Getattr(base.item, "name");
|
||||
basename = createProxyName(c_baseclassname);
|
||||
if (basename)
|
||||
c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
|
||||
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;
|
||||
while (base.item) {
|
||||
if (!GetFlag(base.item, "feature:ignore")) {
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
if (!c_baseclassname) {
|
||||
basenode = base.item;
|
||||
c_baseclassname = baseclassname;
|
||||
basename = createProxyName(c_baseclassname);
|
||||
if (basename)
|
||||
c_baseclass = SwigType_namestr(baseclassname);
|
||||
} else {
|
||||
/* Warn about multiple inheritance for additional base class(es) */
|
||||
String *proxyclassname = Getattr(n, "classtypeobj");
|
||||
Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Base %s of class %s ignored: multiple inheritance is not supported in D.\n", SwigType_namestr(baseclassname), SwigType_namestr(proxyclassname));
|
||||
}
|
||||
String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
|
||||
String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
|
||||
Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Base %s of class %s ignored: multiple inheritance is not supported in D.\n", baseclassname, proxyclassname);
|
||||
base = Next(base);
|
||||
}
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3169,7 +3164,7 @@ private:
|
|||
}
|
||||
} else if (basename && Len(pure_baseclass) > 0) {
|
||||
Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base class %s ignored. Multiple inheritance is not supported in D. "
|
||||
"Warning for %s, base class %s ignored. Multiple inheritance is not supported in D. "
|
||||
"Perhaps you need one of the 'replace' or 'notderived' attributes in the dbase typemap?\n", typemap_lookup_type, pure_baseclass);
|
||||
}
|
||||
|
||||
|
|
|
|||
183
Source/Modules/interface.cxx
Normal file
183
Source/Modules/interface.cxx
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* This file is part of SWIG, which is licensed as a whole under version 3
|
||||
* (or any later version) of the GNU General Public License. Some additional
|
||||
* terms also apply to certain portions of SWIG. The full details of the SWIG
|
||||
* license and copyrights can be found in the LICENSE and COPYRIGHT files
|
||||
* included with the SWIG source code as distributed by the SWIG developers
|
||||
* and at http://www.swig.org/legal.html.
|
||||
*
|
||||
* interface.cxx
|
||||
*
|
||||
* This module contains support for the interface feature.
|
||||
* This feature is used in language modules where the target language does not
|
||||
* naturally support C++ style multiple inheritance, but does support inheritance
|
||||
* from multiple interfaces.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "swigmod.h"
|
||||
|
||||
static bool interface_feature_enabled = false;
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_methods()
|
||||
*
|
||||
* Create a list of all the methods from the base classes of class n that are
|
||||
* marked as an interface. The resulting list is thus the list of methods that
|
||||
* need to be implemented in order for n to be non-abstract.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static List *collect_interface_methods(Node *n) {
|
||||
List *methods = NewList();
|
||||
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 (Cmp(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);
|
||||
}
|
||||
return methods;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* collect_interface_bases
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void collect_interface_bases(Hash *bases, Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
String *name = Getattr(n, "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_interface_base_classes()
|
||||
*
|
||||
* 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_interface_base_classes(Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
// check all bases are also interfaces
|
||||
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")) {
|
||||
Swig_error(Getfile(n), Getline(n), "Base class '%s' of '%s' is not similarly marked as an interface.\n", SwigType_namestr(Getattr(base.item, "name")), SwigType_namestr(Getattr(n, "name")));
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* process_interface_name()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static void process_interface_name(Node *n) {
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
String *interface_name = Getattr(n, "feature:interface:name");
|
||||
if (!Len(interface_name)) {
|
||||
Swig_error(Getfile(n), Getline(n), "The interface feature for '%s' is missing the name attribute.\n", SwigType_namestr(Getattr(n, "name")));
|
||||
SWIG_exit(EXIT_FAILURE);
|
||||
}
|
||||
if (Strchr(interface_name, '%')) {
|
||||
String *name = NewStringf(interface_name, Getattr(n, "sym:name"));
|
||||
Setattr(n, "interface:name", name);
|
||||
} else {
|
||||
Setattr(n, "interface:name", interface_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_interface_propagate_methods()
|
||||
*
|
||||
* Find all the base classes marked as an interface (with feature:interface) for
|
||||
* class node n. For each of these, add all of its methods as methods of n so that
|
||||
* n is not abstract. If class n is also marked as an interface, it will remain
|
||||
* abstract and not have any methods added.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void Swig_interface_propagate_methods(Node *n) {
|
||||
if (interface_feature_enabled) {
|
||||
process_interface_name(n);
|
||||
collect_interface_base_classes(n);
|
||||
List *methods = collect_interface_methods(n);
|
||||
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 *this_decl_resolved = SwigType_typedef_resolve_all(this_decl);
|
||||
bool identically_overloaded_method = false; // true when a base class' method is implemented in n
|
||||
if (SwigType_isfunction(this_decl_resolved)) {
|
||||
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"));
|
||||
identically_overloaded_method = Strcmp(decl, this_decl_resolved) == 0;
|
||||
Delete(decl);
|
||||
if (identically_overloaded_method)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Delete(this_decl_resolved);
|
||||
if (!identically_overloaded_method) {
|
||||
// TODO: Fix if the method is overloaded with different arguments / has default args
|
||||
appendChild(n, mi.item);
|
||||
} else {
|
||||
Delete(mi.item);
|
||||
}
|
||||
}
|
||||
Delete(methods);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_interface_feature_enable()
|
||||
*
|
||||
* Turn on interface feature support
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void Swig_interface_feature_enable() {
|
||||
interface_feature_enabled = true;
|
||||
}
|
||||
|
|
@ -53,6 +53,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 +126,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),
|
||||
|
|
@ -303,6 +305,7 @@ public:
|
|||
SWIG_config_file("java.swg");
|
||||
|
||||
allow_overloading();
|
||||
Swig_interface_feature_enable();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
|
@ -1288,8 +1291,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 +1728,125 @@ public:
|
|||
return Language::pragmaDirective(n);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* getQualifiedInterfaceName()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *getQualifiedInterfaceName(Node *n) {
|
||||
String *ret = Getattr(n, "interface:qname");
|
||||
if (!ret) {
|
||||
String *nspace = Getattr(n, "sym:nspace");
|
||||
String *symname = Getattr(n, "interface:name");
|
||||
if (nspace) {
|
||||
if (package)
|
||||
ret = NewStringf("%s.%s.%s", package, nspace, symname);
|
||||
else
|
||||
ret = NewStringf("%s.%s", nspace, symname);
|
||||
} else {
|
||||
ret = Copy(symname);
|
||||
}
|
||||
Setattr(n, "interface:qname", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* getInterfaceName()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *getInterfaceName(SwigType *t, bool qualified) {
|
||||
String *interface_name = NULL;
|
||||
if (proxy_flag) {
|
||||
Node *n = classLookup(t);
|
||||
if (n && Getattr(n, "interface:name"))
|
||||
interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
|
||||
}
|
||||
return interface_name;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* addInterfaceNameAndUpcasts()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void addInterfaceNameAndUpcasts(SwigType *smart, 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 *interface_name = Getattr(base, "interface:name");
|
||||
if (Len(interface_list))
|
||||
Append(interface_list, ", ");
|
||||
Append(interface_list, interface_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 = NewStringf("%s_GetInterfaceCPtr", interface_name);
|
||||
Replaceall(cptr_method_name, ".", "_");
|
||||
Replaceall(cptr_method_name, "$interfacename", interface_name);
|
||||
|
||||
String *upcast_method_name = Swig_name_member(getNSpace(), proxy_class_name, cptr_method_name);
|
||||
upcastsCode(smart, upcast_method_name, c_classname, c_baseclass);
|
||||
Delete(upcast_method_name);
|
||||
Delete(cptr_method_name);
|
||||
Delete(interface_code);
|
||||
Delete(c_baseclass);
|
||||
}
|
||||
Delete(keys);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* upcastsCode()
|
||||
*
|
||||
* Add code for C++ casting to base class
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void upcastsCode(SwigType *smart, String *upcast_method_name, String *c_classname, String *c_baseclass) {
|
||||
String *jniname = makeValidJniName(upcast_method_name);
|
||||
String *wname = Swig_name_wrapper(jniname);
|
||||
Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method_name);
|
||||
if (smart) {
|
||||
SwigType *bsmart = Copy(smart);
|
||||
SwigType *rclassname = SwigType_typedef_resolve_all(c_classname);
|
||||
SwigType *rbaseclass = SwigType_typedef_resolve_all(c_baseclass);
|
||||
Replaceall(bsmart, rclassname, rbaseclass);
|
||||
Delete(rclassname);
|
||||
Delete(rbaseclass);
|
||||
String *smartnamestr = SwigType_namestr(smart);
|
||||
String *bsmartnamestr = SwigType_namestr(bsmart);
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
|
||||
" jlong baseptr = 0;\n"
|
||||
" ", smartnamestr, " *argp1;\n"
|
||||
" (void)jenv;\n"
|
||||
" (void)jcls;\n"
|
||||
" argp1 = *(", smartnamestr, " **)&jarg1;\n"
|
||||
" *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n"
|
||||
" return baseptr;\n"
|
||||
"}\n", "\n", NIL);
|
||||
Delete(bsmartnamestr);
|
||||
Delete(smartnamestr);
|
||||
Delete(bsmart);
|
||||
} else {
|
||||
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(wname);
|
||||
Delete(jniname);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitProxyClassDefAndCPPCasts()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
@ -1732,9 +1856,12 @@ 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");
|
||||
SwigType *smart = Swig_cparse_smartptr(n);
|
||||
|
||||
// Inheritance from pure Java classes
|
||||
Node *attributes = NewHash();
|
||||
|
|
@ -1747,32 +1874,31 @@ public:
|
|||
if (!purebase_replace) {
|
||||
List *baselist = Getattr(n, "bases");
|
||||
if (baselist) {
|
||||
Iterator base = First(baselist);
|
||||
while (base.item && GetFlag(base.item, "feature:ignore")) {
|
||||
base = Next(base);
|
||||
}
|
||||
if (base.item) {
|
||||
c_baseclassname = Getattr(base.item, "name");
|
||||
baseclass = Copy(getProxyName(c_baseclassname));
|
||||
if (baseclass)
|
||||
c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
|
||||
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));
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
Iterator base = First(baselist);
|
||||
while (base.item) {
|
||||
if (!(GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) {
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
if (!c_baseclassname) {
|
||||
c_baseclassname = baseclassname;
|
||||
baseclass = Copy(getProxyName(baseclassname));
|
||||
if (baseclass)
|
||||
c_baseclass = SwigType_namestr(baseclassname);
|
||||
} else {
|
||||
/* Warn about multiple inheritance for additional base class(es) */
|
||||
String *proxyclassname = Getattr(n, "classtypeobj");
|
||||
Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s, 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(smart, interface_list, interface_upcasts, interface_bases, c_classname);
|
||||
|
||||
bool derived = baseclass && getProxyName(c_baseclassname);
|
||||
if (derived && purebase_notderived)
|
||||
pure_baseclass = empty_string;
|
||||
|
|
@ -1787,13 +1913,15 @@ public:
|
|||
Swig_error(Getfile(n), Getline(n), "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
|
||||
} else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
|
||||
Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java. "
|
||||
"Warning for %s, base %s ignored. Multiple inheritance is not supported in Java. "
|
||||
"Perhaps you need one of the 'replace' or 'notderived' attributes in the javabase typemap?\n", typemap_lookup_type, pure_baseclass);
|
||||
}
|
||||
|
||||
// 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 +1929,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 +1973,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 +1996,8 @@ public:
|
|||
Delete(take_jnicall);
|
||||
}
|
||||
|
||||
Delete(interface_upcasts);
|
||||
Delete(interface_list);
|
||||
Delete(attributes);
|
||||
Delete(destruct);
|
||||
|
||||
|
|
@ -1873,60 +2005,80 @@ public:
|
|||
Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE), // extra Java code
|
||||
"\n", NIL);
|
||||
|
||||
// Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
|
||||
if (derived) {
|
||||
SwigType *smart = Swig_cparse_smartptr(n);
|
||||
String *upcast_method = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
|
||||
String *jniname = makeValidJniName(upcast_method);
|
||||
String *wname = Swig_name_wrapper(jniname);
|
||||
Printf(imclass_cppcasts_code, " public final static native long %s(long jarg1);\n", upcast_method);
|
||||
if (smart) {
|
||||
SwigType *bsmart = Copy(smart);
|
||||
SwigType *rclassname = SwigType_typedef_resolve_all(c_classname);
|
||||
SwigType *rbaseclass = SwigType_typedef_resolve_all(c_baseclass);
|
||||
Replaceall(bsmart, rclassname, rbaseclass);
|
||||
Delete(rclassname);
|
||||
Delete(rbaseclass);
|
||||
String *smartnamestr = SwigType_namestr(smart);
|
||||
String *bsmartnamestr = SwigType_namestr(bsmart);
|
||||
Printv(upcasts_code,
|
||||
"SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
|
||||
" jlong baseptr = 0;\n"
|
||||
" ", smartnamestr, " *argp1;\n"
|
||||
" (void)jenv;\n"
|
||||
" (void)jcls;\n"
|
||||
" argp1 = *(", smartnamestr, " **)&jarg1;\n"
|
||||
" *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n"
|
||||
" return baseptr;\n"
|
||||
"}\n", "\n", NIL);
|
||||
Delete(bsmartnamestr);
|
||||
Delete(smartnamestr);
|
||||
Delete(bsmart);
|
||||
} else {
|
||||
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(wname);
|
||||
Delete(jniname);
|
||||
Delete(upcast_method);
|
||||
Delete(smart);
|
||||
String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
|
||||
upcastsCode(smart, upcast_method_name, c_classname, c_baseclass);
|
||||
Delete(upcast_method_name);
|
||||
}
|
||||
|
||||
Delete(smart);
|
||||
Delete(baseclass);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* classHandler()
|
||||
* emitInterfaceDeclaration()
|
||||
* ---------------------------------------------------------------------- */
|
||||
|
||||
virtual int classHandler(Node *n) {
|
||||
void emitInterfaceDeclaration(Node *n, String *interface_name, 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", interface_name);
|
||||
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, "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");
|
||||
|
||||
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) {
|
||||
return Language::classDeclaration(n);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* 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;
|
||||
|
|
@ -1936,6 +2088,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");
|
||||
String *old_interface_class_code = interface_class_code;
|
||||
interface_class_code = 0;
|
||||
|
||||
if (proxy_flag) {
|
||||
proxy_class_name = NewString(Getattr(n, "sym:name"));
|
||||
|
|
@ -1976,17 +2130,21 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
String *interface_name = Getattr(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
|
||||
if (outerClassesPrefix) {
|
||||
String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
|
||||
if (!addSymbol(proxy_class_name, n, fnspace))
|
||||
return SWIG_ERROR;
|
||||
if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
|
||||
return SWIG_ERROR;
|
||||
if (nspace)
|
||||
Delete(fnspace);
|
||||
Delete(outerClassesPrefix);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (!addSymbol(proxy_class_name, n, nspace))
|
||||
return SWIG_ERROR;
|
||||
if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
|
||||
return SWIG_ERROR;
|
||||
}
|
||||
|
||||
// Each outer proxy class goes into a separate file
|
||||
|
|
@ -2022,11 +2180,27 @@ public:
|
|||
destructor_call = NewString("");
|
||||
destructor_throws_clause = NewString("");
|
||||
proxy_class_constants_code = NewString("");
|
||||
|
||||
if (Getattr(n, "feature:interface")) {
|
||||
interface_class_code = NewString("");
|
||||
String *output_directory = outputDirectory(nspace);
|
||||
String *filen = NewStringf("%s%s.java", output_directory, interface_name);
|
||||
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, interface_name, interface_class_code, nspace);
|
||||
Delete(filen);
|
||||
Delete(output_directory);
|
||||
}
|
||||
}
|
||||
|
||||
Language::classHandler(n);
|
||||
|
||||
if (proxy_flag) {
|
||||
|
||||
emitProxyClassDefAndCPPCasts(n);
|
||||
|
||||
String *javaclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
|
||||
|
|
@ -2034,18 +2208,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);
|
||||
|
|
@ -2110,8 +2288,16 @@ public:
|
|||
Delete(downcast_method);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -2203,6 +2389,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 +2440,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 +2530,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 +2560,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))) {
|
||||
|
|
@ -3068,6 +3266,50 @@ public:
|
|||
substitution_performed = true;
|
||||
Delete(classnametype);
|
||||
}
|
||||
if (Strstr(tm, "$javainterfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$javainterfacename", jnidescriptor, true);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$*javainterfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
Delete(SwigType_pop(interfacenametype));
|
||||
if (Len(interfacenametype) > 0) {
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*javainterfacename", jnidescriptor, true);
|
||||
substitution_performed = true;
|
||||
}
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$&javainterfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
SwigType_add_pointer(interfacenametype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&javainterfacename", jnidescriptor, true);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$interfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", jnidescriptor, false);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$*interfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
Delete(SwigType_pop(interfacenametype));
|
||||
if (Len(interfacenametype) > 0) {
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", jnidescriptor, false);
|
||||
substitution_performed = true;
|
||||
}
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
if (Strstr(tm, "$&interfacename")) {
|
||||
SwigType *interfacenametype = Copy(strippedtype);
|
||||
SwigType_add_pointer(interfacenametype);
|
||||
substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", jnidescriptor, false);
|
||||
substitution_performed = true;
|
||||
Delete(interfacenametype);
|
||||
}
|
||||
|
||||
Delete(strippedtype);
|
||||
Delete(type);
|
||||
|
|
@ -3116,6 +3358,24 @@ public:
|
|||
Delete(replacementname);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* substituteInterfacenameSpecialVariable()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool jnidescriptor, bool qualified) {
|
||||
|
||||
String *interfacename = getInterfaceName(interfacenametype/*, jnidescriptor*/, qualified);
|
||||
if (interfacename) {
|
||||
String *replacementname = Copy(interfacename);
|
||||
|
||||
if (jnidescriptor)
|
||||
Replaceall(replacementname,".","/");
|
||||
Replaceall(tm, interfacenamespecialvariable, replacementname);
|
||||
|
||||
Delete(replacementname);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* emitTypeWrapperClass()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
|
@ -3273,7 +3533,7 @@ public:
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) {
|
||||
String *proxyClassName = 0;
|
||||
String *pgcpp_java_type = 0;
|
||||
String *jtype = NewString(Getattr(p, "tmap:jtype"));
|
||||
|
||||
// Strip C comments
|
||||
|
|
@ -3290,11 +3550,9 @@ public:
|
|||
if (Cmp(jtype, "long") == 0) {
|
||||
if (proxy_flag) {
|
||||
if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) {
|
||||
String *proxyname = getProxyName(t);
|
||||
if (proxyname) {
|
||||
// Found a struct/class parameter passed by value, reference, pointer, or pointer reference
|
||||
proxyClassName = proxyname;
|
||||
} else {
|
||||
String *interface_name = getInterfaceName(t, true);
|
||||
pgcpp_java_type = interface_name ? interface_name : getProxyName(t);
|
||||
if (!pgcpp_java_type) {
|
||||
// Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types
|
||||
String *jstype = NewString(Getattr(p, "tmap:jstype"));
|
||||
if (jstype) {
|
||||
|
|
@ -3316,7 +3574,7 @@ public:
|
|||
if (cls && !Getattr(cls, "feature:ignore")) {
|
||||
String *symname = Getattr(cls, "sym:name");
|
||||
if (symname && Strcmp(symname, jstype) == 0) {
|
||||
proxyClassName = symname;
|
||||
pgcpp_java_type = symname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3328,7 +3586,7 @@ public:
|
|||
}
|
||||
}
|
||||
Delete(jtype);
|
||||
return proxyClassName;
|
||||
return pgcpp_java_type;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -3118,6 +3118,31 @@ int Language::addSymbol(const String *s, const Node *n, const_String_or_char_ptr
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Language::addInterfaceSymbol()
|
||||
*
|
||||
* Adds a symbol entry into the target language symbol tables - for the interface
|
||||
* feature only.
|
||||
* Returns 1 if the symbol is added successfully.
|
||||
* The scope is as per addSymbol.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int Language::addInterfaceSymbol(const String *interface_name, Node *n, const_String_or_char_ptr scope) {
|
||||
if (interface_name) {
|
||||
Node *existing_symbol = symbolLookup(interface_name, scope);
|
||||
if (existing_symbol) {
|
||||
String *proxy_class_name = Getattr(n, "sym:name");
|
||||
Swig_error(input_file, line_number, "The interface feature name '%s' for proxy class '%s' is already defined in the generated target language module in scope '%s'.\n",
|
||||
interface_name, proxy_class_name, scope);
|
||||
Swig_error(Getfile(existing_symbol), Getline(existing_symbol), "Previous declaration of '%s'\n", interface_name);
|
||||
return 0;
|
||||
}
|
||||
if (!addSymbol(interface_name, n, scope))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Language::symbolAddScope()
|
||||
*
|
||||
|
|
@ -3214,7 +3239,7 @@ void Language::dumpSymbols() {
|
|||
* Language::symbolLookup()
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
Node *Language::symbolLookup(String *s, const_String_or_char_ptr scope) {
|
||||
Node *Language::symbolLookup(const String *s, const_String_or_char_ptr scope) {
|
||||
Hash *symbols = Getattr(symtabs, scope ? scope : "");
|
||||
if (!symbols) {
|
||||
return NULL;
|
||||
|
|
@ -3797,6 +3822,7 @@ String *Language::defaultExternalRuntimeFilename() {
|
|||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Language::replaceSpecialVariables()
|
||||
*
|
||||
* Language modules should implement this if special variables are to be handled
|
||||
* correctly in the $typemap(...) special variable macro.
|
||||
* method - typemap method name
|
||||
|
|
@ -3816,3 +3842,4 @@ Language *Language::instance() {
|
|||
Hash *Language::getClassHash() const {
|
||||
return classhash;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2176,20 +2176,24 @@ MODULA3():
|
|||
|
||||
/* Deal with inheritance */
|
||||
List *baselist = Getattr(n, "bases");
|
||||
if (baselist != NIL) {
|
||||
if (baselist) {
|
||||
Iterator base = First(baselist);
|
||||
if (base.item) {
|
||||
c_baseclassname = Getattr(base.item, "name");
|
||||
baseclass = Copy(getProxyName(c_baseclassname));
|
||||
if (baseclass) {
|
||||
c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
|
||||
while (base.item) {
|
||||
if (!GetFlag(base.item, "feature:ignore")) {
|
||||
String *baseclassname = Getattr(base.item, "name");
|
||||
if (!c_baseclassname) {
|
||||
c_baseclassname = baseclassname;
|
||||
baseclass = Copy(getProxyName(baseclassname));
|
||||
if (baseclass)
|
||||
c_baseclass = SwigType_namestr(baseclassname);
|
||||
} else {
|
||||
/* Warn about multiple inheritance for additional base class(es) */
|
||||
String *proxyclassname = Getattr(n, "classtypeobj");
|
||||
Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s, base %s ignored. Multiple inheritance is not supported in Modula 3.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
|
||||
}
|
||||
}
|
||||
base = Next(base);
|
||||
if (base.item != NIL) {
|
||||
Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
|
||||
name, Getattr(base.item, "name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2201,7 +2205,7 @@ MODULA3():
|
|||
const String *pure_baseclass = typemapLookup(n, "m3base", name, WARN_NONE);
|
||||
if (hasContent(pure_baseclass) && hasContent(baseclass)) {
|
||||
Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n", name, pure_baseclass);
|
||||
"Warning for %s, base %s ignored. Multiple inheritance is not supported in Modula 3.\n", name, pure_baseclass);
|
||||
}
|
||||
// Pure Modula 3 interfaces
|
||||
const String *pure_interfaces = typemapLookup(n, derived ? "m3interfaces_derived" : "m3interfaces",
|
||||
|
|
@ -2431,7 +2435,7 @@ MODULA3():
|
|||
base = Next(base);
|
||||
if (base.item) {
|
||||
Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
|
||||
"Warning for %s, base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
|
||||
proxy_class_name, Getattr(base.item, "name"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2018,7 +2018,7 @@ done:
|
|||
String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
|
||||
String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
|
||||
Swig_warning(WARN_PHP_MULTIPLE_INHERITANCE, input_file, line_number,
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname);
|
||||
"Warning for %s, base %s ignored. Multiple inheritance is not supported in PHP.\n", proxyclassname, baseclassname);
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2473,7 +2473,7 @@ public:
|
|||
String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
|
||||
String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
|
||||
Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
|
||||
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Ruby.\n", proxyclassname, baseclassname);
|
||||
"Warning for %s, base %s ignored. Multiple inheritance is not supported in Ruby.\n", proxyclassname, baseclassname);
|
||||
base = Next(base);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,8 +208,9 @@ public:
|
|||
/* Miscellaneous */
|
||||
virtual int validIdentifier(String *s); /* valid identifier? */
|
||||
virtual int addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope = ""); /* Add symbol */
|
||||
virtual int addInterfaceSymbol(const String *interface_name, Node *n, const_String_or_char_ptr scope = "");
|
||||
virtual void dumpSymbols();
|
||||
virtual Node *symbolLookup(String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */
|
||||
virtual Node *symbolLookup(const String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */
|
||||
virtual Hash* symbolAddScope(const_String_or_char_ptr scope);
|
||||
virtual Hash* symbolScopeLookup(const_String_or_char_ptr scope);
|
||||
virtual Hash* symbolScopePseudoSymbolLookup(const_String_or_char_ptr scope);
|
||||
|
|
@ -422,19 +423,24 @@ extern "C" {
|
|||
}
|
||||
|
||||
/* Contracts */
|
||||
|
||||
void Swig_contracts(Node *n);
|
||||
void Swig_contract_mode_set(int flag);
|
||||
int Swig_contract_mode_get();
|
||||
|
||||
/* Browser */
|
||||
|
||||
void Swig_browser(Node *n, int);
|
||||
void Swig_default_allocators(Node *n);
|
||||
void Swig_process_types(Node *n);
|
||||
|
||||
/* Nested classes */
|
||||
void Swig_nested_process_classes(Node *n);
|
||||
void Swig_nested_name_unnamed_c_structs(Node *n);
|
||||
|
||||
/* Interface feature */
|
||||
void Swig_interface_feature_enable();
|
||||
void Swig_interface_propagate_methods(Node *n);
|
||||
|
||||
/* Miscellaneous */
|
||||
template <class T> class save_value {
|
||||
T _value;
|
||||
T& _value_ptr;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue