From cd6c8806f08f9482b80102f3fa87bbc7f93178a0 Mon Sep 17 00:00:00 2001
From: William S Fulton
+By default SWIG wraps all C++ classes as Java classes.
+As Java only supports derivation from a single base class, SWIG has to ignore all
+bases except the first when a C++ class inherits from more than one base class.
+However, there is a family of SWIG macros that change the default wrapping and allows a C++ class
+to be wrapped as a Java interface instead of a Java class.
+These macros provide a way to support some sort of multiple inheritance as there is no limit to
+the number of interfaces that a Java class can inherit from.
+
+When a C++ class is wrapped as a Java interface, a Java proxy class is still needed.
+The swiginterface.i library file provides three macros for marking a C++ class to be
+wrapped as a Java interface.
+There is more than one macro in order to provide a choice for choosing the Java interface and Java proxy names.
+
+The table below has a few examples showing the resulting proxy and interface names.
+
+The 2nd last example shows the names used in the string formatting functions.
+The input for PROXY that "%s" expands to is the proxy name, that is, Base.
+The input for INTERFACE that "%s" expands to is the proxy name, that is, BaseProxy.
+
+The last example shows rstrip and in this case strips the Proxy suffix and then adds on Interface.
+
+Consider the following C++ code:
+
+By default all classes are wrapped and are available in Java, but, Derived
+has all bases ignored except the first.
+SWIG generates a warning for the above code:
+
+If we decide to wrap the two base classes as interfaces and add the following before SWIG parses the above example code:
+
+then two interface files are generated, Base1.java and Base2.java in addition to proxy class files, Base1SwigImpl.java and Base2SwigImpl.java.
+The contents of interface file Base1.java for Base1 is shown below:
+
+The proxy class in Base1SwigImpl.java for Base1 is as it would have been if %interface was not used,
+except the name has changed to Base1SwigImpl and it implements the appropriate base:
+
+In fact any class deriving from Base will now implement the interface instead of
+deriving from it (or ignoring the base in the case of multiple base classes).
+Hence the Derived proxy class will now implement both bases:
+
+Wherever a class marked as an interface is used, such as the UseBases method in the example,
+the interface name is used as the type in the Java layer:
+
+Note that each Java interface has a method added to obtain the correct C++ pointer for passing to the native function -
+Base1_GetInterfaceCPtr for Base1.
+This method is similar to the getCPtr method in the proxy classes.
+In fact, as shown above in the Derived class, the proxy classes implement
+this generated interface by calling a native method (Derived_Base1_GetInterfaceCPtr)
+which calls an appropriate C++ cast of the pointer up the inheritance chain.
+
+The interface macros are implemented using the interface feature and typemaps.
+For example:
+
+The feature accepts one attribute called name, which is the name of the Java interface mentioned earlier.
+The INTERFACE_TYPEMAPS macro implements the typemaps and can be viewed in the
+swiginterface.i file and contain
+the usual Java typemaps for generating code plus the javainterfacecode
+typemap which is only used when a class is marked with the interface feature.
+See Java code typemaps for details.
+
diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html
index dae6edc01..08309d9f7 100644
--- a/Doc/Manual/Java.html
+++ b/Doc/Manual/Java.html
@@ -83,6 +83,7 @@
+
@@ -3331,6 +3332,251 @@ public final class Beverage {
+
25.4.6 Interfaces
+
+
+
+
+
+
+
+Interface Macro Name
+ Description
+
+
+%interface(CTYPE)
+ Proxy class name is unchanged, interface name has SwigInterface added as a suffix for C++ class CTYPE.
+
+
+%interface_impl(CTYPE)
+ Proxy class name has SwigImpl as a suffix, interface name has SwigInterface added as a suffix for C++ class CTYPE.
+
+
+%interface_custom("PROXY", "INTERFACE", CTYPE)
+ Proxy class name is given by the string PROXY, interface name is given by the string INTERFACE for C++ class CTYPE. The PROXY and INTERFACE names can use the string formatting functions used in %rename.
+
+
+
+
+
+Example Usage
+ Proxy Class Name
+ Interface Class Name
+
+
+%interface(Base)
+ Base
+ BaseSwigInterface
+
+
+%interface_impl(Base)
+ BaseSwigImpl
+ Base
+
+
+%interface_custom("BaseProxy", "IBase", Base)
+ BaseProxy
+ IBase
+
+
+%interface_custom("%sProxy", "IBase", Base)
+ BaseProxy
+ IBase
+
+
+%interface_custom("%sProxy", "%sInterface", Base)
+ BaseProxy
+ BaseProxyInterface
+
+
+%interface_custom("%sProxy", "%(rstrip:[Proxy])sInterface", Base)
+ BaseProxy
+ BaseInterface
+
+namespace Space {
+ struct Base1 {
+ virtual void Method1();
+ };
+ struct Base2 {
+ virtual void Method2();
+ };
+ struct Derived : Base1, Base2 {
+ };
+ void UseBases(const Base1 &b1, const Base2 &b2);
+}
+
+
+example.i:10: Warning 813: Warning for Derived, base Base2 ignored.
+Multiple inheritance is not supported in Java.
+
+
+%include <swiginterface.i>
+%interface_impl(Space::Base1);
+%interface_impl(Space::Base2);
+
+
+public interface Base1 {
+ long Base1_GetInterfaceCPtr();
+ void Method1();
+}
+
+
+public class Base1SwigImpl implements Base1 {
+...
+ public long Base1_GetInterfaceCPtr() {
+ return exampleJNI.Base1SwigImpl_Base1_GetInterfaceCPtr(swigCPtr);
+ }
+
+ public void Method1() {
+ exampleJNI.Base1SwigImpl_Method1(swigCPtr, this);
+ }
+...
+}
+
+
+public class Derived implements Base1, Base2 {
+...
+ public long Base1_GetInterfaceCPtr() {
+ return exampleJNI.Derived_Base1_GetInterfaceCPtr(swigCPtr);
+ }
+
+ public long Base2_GetInterfaceCPtr() {
+ return exampleJNI.Derived_Base2_GetInterfaceCPtr(swigCPtr);
+ }
+
+ public void Method1() {
+ exampleJNI.Derived_Method1(swigCPtr, this);
+ }
+
+ public void Method2() {
+ exampleJNI.Derived_Method2(swigCPtr, this);
+ }
+...
+}
+
+
+ public static void UseBases(Base1 b1, Base2 b2) {
+ exampleJNI.UseBases(b1.Base1_GetInterfaceCPtr(), b1, b2.Base2_GetInterfaceCPtr(), b2);
+ }
+
+
+%define %interface(CTYPE...)
+%feature("interface", name="%sSwigInterface") CTYPE;
+INTERFACE_TYPEMAPS(CTYPE)
+%enddef
+
+25.5 Cross language polymorphism using directors
@@ -5585,6 +5831,8 @@ For example, $javaclassname is replaced by the proxy classname Foo<
expands to the proxy classname when wrapping Foo *&.
If the type does not have an associated proxy class, it expands to the type wrapper class name, for example,
SWIGTYPE_p_unsigned_short is generated when wrapping unsigned short *.
+The class name is fully qualified with the package name when using the
+nspace feature.
@@ -5715,6 +5963,35 @@ This special variable expands to the intermediary class name. Usually this is th unless the jniclassname attribute is specified in the %module directive.
+
+$javainterfacename
+This special variable is only expanded when the interface feature is applied to a class.
+It works much like $javaclassname, but instead of expanding to the proxy classname,
+it expands to the value in the name attribute in the interface feature.
+For example:
+
+%feature("interface", name="MyInterface") MyClass; +%typemap(jstype) MyClass "$&javainterfacename" +%typemap(jstype) MyClass * "$javainterfacename" +
+will result in the jstype typemap expanding to MyInterface for both +MyClass and MyClass *. +The interface name is fully qualified with the package name when using the +nspace feature. +
+ +
+$interfacename
+This special variable is only expanded when the interface feature is applied to a class.
+It expands to just the interface name and is thus different to $javainterfacename
+in that it is not fully qualified with the package name when using the
+nspace feature.
+
%typemap(javainterfacecode, declaration="...", cptrmethod="...")
++The code in this typemap is added to the body of a Java proxy class but only when a class is +marked with the interface feature. +The typemap is used in the proxy class marked with the interface feature as well as all proxy classes derived from the marked C++ class, +as they are all generated as implementing the Java interface. +The default typemap used in the %interface family of macros mentioned in +the Java interfaces section, +where CTYPE is the C++ class macro argument, +is as follows: +
+ ++%typemap(javainterfacecode, + declaration=" long $interfacename_GetInterfaceCPtr();\n", + cptrmethod="$interfacename_GetInterfaceCPtr") CTYPE %{ + public long $interfacename_GetInterfaceCPtr() { + return $imclassname.$javaclazzname$interfacename_GetInterfaceCPtr(swigCPtr); + } +%} +
+The special variable $interfacename is expanded into the +name specified in the interface feature. +
+Compatibility Note: In SWIG-1.3.21 and earlier releases, typemaps called "javagetcptr" and "javaptrconstructormodifiers" were available. These are deprecated and the "javabody" typemap can be used instead. +The javainterfacecode typemap and interface feature was introduced in SWIG-3.0.9.
@@ -5866,6 +6173,7 @@ In summary the contents of the typemaps make up a proxy class like this: [ javafinalize typemap ] public synchronized void delete() [ javadestruct OR javadestruct_derived typemap ] [ javacode typemap ] +[ javainterfacecode typemap] ... proxy functions ... } @@ -5875,6 +6183,11 @@ public synchronized void delete() [ javadestruct OR javadestruct_derived Note the delete() methodname and method modifiers are configurable, see "javadestruct" and "javadestruct_derived" typemaps above.
++The javainterfacecode typemap is only used when bases are marked by the interface +feature and the implements list will also then be expanded to include these Java interfaces. +
+The type wrapper class is similar in construction:
@@ -5907,8 +6220,23 @@ The type wrapper class is similar in construction: The "javaimports" typemap is ignored if the enum class is wrapped by an inner Java class, that is when wrapping an enum declared within a C++ class. +The Java interface turned on by the interface feature is fairly simple:
++[ javaimports typemap ] +public interface [ javainterfacename ] { +[ javainterfacecode:cptrmethod typemap attribute ] +... interface declarations ... +} ++
+where javainterfacename is the name attribute in the interface feature. +
+-The defaults can be overridden to tailor these classes. +The defaults can be overridden to tailor the generated classes. Here is an example which will change the getCPtr method and constructor from the default public access to protected access. If the classes in one package are not using the classes in another package, then these methods need not be public and removing access to these low level implementation details, is a good thing. If you are invoking SWIG more than once and generating the wrapped classes into different packages in each invocation, then you cannot do this as you will then have different packages. -- cgit v1.2.1