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))) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue