mirror of https://github.com/swig/swig
Add the %interface_additional macro
New macro added to the family of %interface macros. This new macro is for adding additional interfaces for the generated interface to extend/derive from. Closes #1188
This commit is contained in:
parent
f93cf07015
commit
cbff768feb
|
@ -7,6 +7,11 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
|
|||
Version 4.3.0 (in progress)
|
||||
===========================
|
||||
|
||||
2024-09-11: wsfulton
|
||||
[C# Java] #1188 Add the %interface_additional macro to the family of
|
||||
%interface macros for adding additional interfaces for the generated
|
||||
interface to extend/derive from.
|
||||
|
||||
2024-09-07: wsfulton
|
||||
#2875 Fix swig-4.1.0 regression using the %interface family of macros
|
||||
for multiple inheritance and common bases.
|
||||
|
|
|
@ -3445,6 +3445,10 @@ There is more than one macro in order to provide a choice for choosing the Java
|
|||
<td><tt>%interface_custom("PROXY", "INTERFACE", CTYPE)</tt></td>
|
||||
<td>For C++ class <tt>CTYPE</tt>, proxy class name is given by the string <tt>PROXY</tt>, interface name is given by the string <tt>INTERFACE</tt>. The <tt>PROXY</tt> and <tt>INTERFACE</tt> names can use the <a href="SWIG.html#SWIG_advanced_renaming">string formatting functions</a> used in <tt>%rename</tt>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><tt>%interface_additional("PROXY", "INTERFACE", "ADDITIONAL", CTYPE)</tt></td>
|
||||
<td>For C++ class <tt>CTYPE</tt>, proxy class name is given by the string <tt>PROXY</tt>, interface name is given by the string <tt>INTERFACE</tt>. The <tt>PROXY</tt> and <tt>INTERFACE</tt> names can use the <a href="SWIG.html#SWIG_advanced_renaming">string formatting functions</a> used in <tt>%rename</tt>. <tt>ADDITIONAL</tt> should contain a comma separated list of interfaces for the interface class to additionally extend. This is for adding interfaces not parsed by SWIG and is useful for adding in pure Java interfaces</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
|
@ -3648,8 +3652,82 @@ which calls an appropriate C++ cast of the pointer up the inheritance chain.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
The <tt>%interface_additional</tt> macro is useful for adding additional interfaces to the Java interface class.
|
||||
Consider a simple class hierarchy, where <tt>Whizz</tt> inherits from <tt>Bang</tt> and we want
|
||||
these two classes to be wrapped as Java interfaces and the <tt>Whizz</tt> interface to additionally extend from the pure Java interface <tt>java.util.EventListener</tt>.
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%interface_custom("Bang", "IBang", Space::Bang);
|
||||
%interface_additional("Whizz", "IWhizz", "java.util.EventListener", Space::Whizz)
|
||||
|
||||
namespace Space {
|
||||
struct Bang {
|
||||
virtual void bang() = 0;
|
||||
};
|
||||
struct Whizz : Bang {
|
||||
virtual void whizz() = 0;
|
||||
};
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The classes and interfaces generated are shown below, noting that <tt>IWhizz</tt> extends the additional interface <tt>java.util.EventListener</tt>:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
public interface IBang { ... }
|
||||
|
||||
public interface IWhizz extends java.util.EventListener, IBang { ... }
|
||||
|
||||
public class Bang implements IBang { ... }
|
||||
|
||||
public class Whizz implements IWhizz, IBang { ... }
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Note the subtle difference to the <tt>javainterfaces</tt> typemap discussed elsewhere.
|
||||
The typemap applies to the generated Java proxy class only, not the Java interface.
|
||||
A slight change to our example above as follows:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
%interface_custom("Bang", "IBang", Space::Bang);
|
||||
%interface_custom("Whizz", "IWhizz", Space::Whizz)
|
||||
%typemap(javainterfaces) Space::Whizz "java.util.EventListener"
|
||||
|
||||
namespace Space {
|
||||
... as shown above ...
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
will then the generate different code for the proxy class <tt>Whizz</tt> and the interface <tt>IWhizz</tt> as follows:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
public interface IBang { ... }
|
||||
|
||||
public interface IWhizz extends IBang { ... }
|
||||
|
||||
public class Bang implements IBang { ... }
|
||||
|
||||
public class Whizz implements IWhizz, IBang, java.util.EventListener { ... }
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Finally, a note on the implementation of the interface macros.
|
||||
The interface macros are implemented using the <tt>interface</tt> feature and typemaps.
|
||||
For example:
|
||||
A couple of examples:
|
||||
</p>
|
||||
|
||||
<div class="code">
|
||||
|
@ -3658,18 +3736,30 @@ For example:
|
|||
%feature("interface", name="%sSwigInterface") CTYPE;
|
||||
INTERFACE_TYPEMAPS(CTYPE)
|
||||
%enddef
|
||||
|
||||
%define %interface_additional(PROXY, INTERFACE, ADDITIONAL, CTYPE...)
|
||||
%rename(PROXY) CTYPE;
|
||||
%feature("interface", name=INTERFACE, additional=ADDITIONAL) CTYPE;
|
||||
INTERFACE_TYPEMAPS(CTYPE)
|
||||
%enddef
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
The feature accepts one attribute called <tt>name</tt>, which is the name of the Java interface mentioned earlier.
|
||||
The feature accepts two attributes named <tt>name</tt> and <tt>additional</tt>.
|
||||
The <tt>name</tt> attribute should contain the name of the Java interface.
|
||||
The <tt>additional</tt> attribute should contain additional interfaces for the interface class, not parsed by SWIG.
|
||||
The <tt>INTERFACE_TYPEMAPS</tt> macro implements the typemaps and can be viewed in the
|
||||
<tt>swiginterface.i</tt> file and contain
|
||||
<tt>swiginterface.i</tt> file and contains
|
||||
the usual Java typemaps for generating code plus the <tt>javainterfacecode</tt>
|
||||
typemap which is only used when a class is marked with the <tt>interface</tt> feature.
|
||||
See <a href="Java.html#Java_code_typemaps">Java code typemaps</a> for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Compatibility note:</b> The <tt>additional</tt> attribute and <tt>%interface_additional</tt> macro was added in SWIG-4.3.0.
|
||||
</p>
|
||||
|
||||
<H2><a name="Java_directors">27.5 Cross language polymorphism using directors</a></H2>
|
||||
|
||||
|
||||
|
@ -6987,7 +7077,7 @@ The "javaimports" typemap is ignored if the enum class is wrapped by an inner Ja
|
|||
<div class="code">
|
||||
<pre>
|
||||
[ javaimports typemap ]
|
||||
[ javainterfacemodifiers typemap ] [ javainterfacename ] {
|
||||
[ javainterfacemodifiers typemap ] [ name ] [extends additional [, ...] ] {
|
||||
[ javainterfacecode:cptrmethod typemap attribute ]
|
||||
... interface declarations ...
|
||||
}
|
||||
|
@ -6995,7 +7085,9 @@ The "javaimports" typemap is ignored if the enum class is wrapped by an inner Ja
|
|||
</div>
|
||||
|
||||
<p>
|
||||
where <tt>javainterfacename</tt> is the <tt>name</tt> attribute in the <a href="Java.html#Java_interfaces">interface feature</a>.
|
||||
where <tt>name</tt> is the <tt>name</tt> attribute and
|
||||
<tt>additional</tt> is the <tt>additional</tt> attribute
|
||||
in the <a href="Java.html#Java_interfaces">interface feature</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
@ -130,3 +130,48 @@ namespace Space {
|
|||
};
|
||||
}
|
||||
%}
|
||||
|
||||
// Test additional interfaces - these are designed for non-C++ interfaces
|
||||
#if defined(SWIGJAVA) || defined(SWIGCSHARP)
|
||||
%interface_custom("Additional1", "IAdditional1", IAdditional1)
|
||||
#endif
|
||||
|
||||
#if defined(SWIGJAVA)
|
||||
%interface_additional("Additional2", "IAdditional2", "java.util.EventListener", IAdditional2)
|
||||
%interface_additional("Additional3", "IAdditional3", "java.util.EventListener", IAdditional3)
|
||||
#elif defined(SWIGCSHARP)
|
||||
%interface_additional("Additional2", "IAdditional2", "global::System.ICloneable", IAdditional2)
|
||||
%interface_additional("Additional3", "IAdditional3", "global::System.ICloneable", IAdditional3)
|
||||
%extend IAdditional2 {
|
||||
%proxycode %{
|
||||
public virtual object Clone() {
|
||||
return new Additional2(this);
|
||||
}
|
||||
%}
|
||||
}
|
||||
%extend IAdditional3 {
|
||||
%proxycode %{
|
||||
public virtual object Clone() {
|
||||
return new Additional3(this);
|
||||
}
|
||||
%}
|
||||
}
|
||||
%extend AdditionalConcrete {
|
||||
%proxycode %{
|
||||
public virtual object Clone() {
|
||||
return new AdditionalConcrete(this);
|
||||
}
|
||||
%}
|
||||
}
|
||||
#endif
|
||||
|
||||
%copyctor AdditionalConcrete;
|
||||
%copyctor IAdditional2;
|
||||
%copyctor IAdditional3;
|
||||
|
||||
%inline %{
|
||||
struct IAdditional1 { virtual ~IAdditional1() {} };
|
||||
struct IAdditional2 { virtual ~IAdditional2() {} };
|
||||
struct IAdditional3 : IAdditional1, IAdditional2 {};
|
||||
struct AdditionalConcrete : IAdditional1, IAdditional2 {};
|
||||
%}
|
||||
|
|
|
@ -61,3 +61,8 @@ INTERFACE_TYPEMAPS(CTYPE)
|
|||
INTERFACE_TYPEMAPS(CTYPE)
|
||||
%enddef
|
||||
|
||||
%define %interface_additional(PROXY, INTERFACE, ADDITIONAL, CTYPE...)
|
||||
%rename(PROXY) CTYPE;
|
||||
%feature("interface", name=INTERFACE, additional=ADDITIONAL) CTYPE;
|
||||
INTERFACE_TYPEMAPS(CTYPE)
|
||||
%enddef
|
||||
|
|
|
@ -72,3 +72,8 @@ INTERFACE_TYPEMAPS(CTYPE)
|
|||
INTERFACE_TYPEMAPS(CTYPE)
|
||||
%enddef
|
||||
|
||||
%define %interface_additional(PROXY, INTERFACE, ADDITIONAL, CTYPE...)
|
||||
%rename(PROXY) CTYPE;
|
||||
%feature("interface", name=INTERFACE, additional=ADDITIONAL) CTYPE;
|
||||
INTERFACE_TYPEMAPS(CTYPE)
|
||||
%enddef
|
||||
|
|
|
@ -2103,8 +2103,10 @@ public:
|
|||
Printv(f_interface, typemapLookup(n, "csimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
|
||||
Printv(f_interface, typemapLookup(n, "csinterfacemodifiers", Getattr(n, "classtypeobj"), WARN_CSHARP_TYPEMAP_INTERFACEMODIFIERS_UNDEF), NIL);
|
||||
Printf(f_interface, " %s", interface_name);
|
||||
|
||||
String *additional = Getattr(n, "feature:interface:additional");
|
||||
String *bases = additional ? NewStringf(" : %s", additional) : 0;
|
||||
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") || !GetFlag(base.item, "feature:interface"))
|
||||
continue; // TODO: warn about skipped non-interface bases
|
||||
|
@ -2116,10 +2118,10 @@ public:
|
|||
Append(bases, base_iname);
|
||||
}
|
||||
}
|
||||
if (bases) {
|
||||
Printv(f_interface, bases, NIL);
|
||||
Delete(bases);
|
||||
}
|
||||
}
|
||||
if (bases) {
|
||||
Printv(f_interface, bases, NIL);
|
||||
Delete(bases);
|
||||
}
|
||||
Printf(f_interface, " {\n");
|
||||
|
||||
|
|
|
@ -2094,8 +2094,10 @@ public:
|
|||
Printv(f_interface, typemapLookup(n, "javaimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
|
||||
Printv(f_interface, typemapLookup(n, "javainterfacemodifiers", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACEMODIFIERS_UNDEF), NIL);
|
||||
Printf(f_interface, " %s", interface_name);
|
||||
|
||||
String *additional = Getattr(n, "feature:interface:additional");
|
||||
String *bases = additional ? Copy(additional) : 0;
|
||||
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") || !GetFlag(base.item, "feature:interface"))
|
||||
continue; // TODO: warn about skipped non-interface bases
|
||||
|
@ -2107,10 +2109,10 @@ public:
|
|||
Append(bases, base_iname);
|
||||
}
|
||||
}
|
||||
if (bases) {
|
||||
Printv(f_interface, " extends ", bases, NIL);
|
||||
Delete(bases);
|
||||
}
|
||||
}
|
||||
if (bases) {
|
||||
Printv(f_interface, " extends ", bases, NIL);
|
||||
Delete(bases);
|
||||
}
|
||||
Printf(f_interface, " {\n");
|
||||
|
||||
|
|
Loading…
Reference in New Issue