diff --git a/CHANGES.current b/CHANGES.current index 04a7e277b..a4fd78430 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -7,6 +7,24 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/ Version 3.0.12 (in progress) ============================ +2017-01-13: wsfulton + [C# D Java] Add new %proxycode directive which is a macro for %insert("proxycode"). + This is a way of adding pure C#/D/Java code into the appropriate proxy class, eg: + + %extend Proxy2 { + %proxycode %{ + public int proxycode2(int i) { + return i+2; + } + %} + } + + %inline %{ + struct Proxy2 {}; + %} + + There will then be a pure Java/C#/D method called proxycode2 in the Proxy2 class. + 2016-12-31: ajrheading1 Issue #860 - Remove use of std::unary_function and std::binary_function which is deprecated in C++11. diff --git a/Doc/Manual/Contents.html b/Doc/Manual/Contents.html index 11a90c4c3..f196da53c 100644 --- a/Doc/Manual/Contents.html +++ b/Doc/Manual/Contents.html @@ -1016,6 +1016,7 @@
dconstructor, ddestructor, ddispose and ddispose_derived are used to generate the class constructor, destructor and dispose() method, respectively. The auxiliary code for handling the pointer to the C++ object is stored in dbody and dbody_derived. You can override them for specific types.
++Code can also be injected into the D proxy class using %proxycode. +
+The previous section described how to extend a wrapped class with C or C++ code. +This section describes how to extend a wrapped class with Java code instead of C/C++ code. +The %proxycode directive is used and is just a macro for %insert("proxycode"). +The Code insertion block section describes the %insert directive. +The section of code for insertion is "proxycode", that is, the Java proxy class. +This directive must hence only be used within the scope of a class, otherwise it is silently ignored. +There are two common ways to get the scope correct. +
+ ++The first is to use %proxycode inside a class that SWIG parses, for example a toString() method can be added to a C++ class using pure Java code. +A C++ header file can mix C++ and Java code inside the C++ class as follows: +
+ +
+// flag.h header file
+class Flag {
+ bool flag;
+public:
+ Flag(bool flag) : flag(flag) {}
+ bool FetchFlag() { return flag; }
+#if defined(SWIG)
+%proxycode %{
+ public String toString() {
+ boolean flag = FetchFlag();
+ return Boolean.toString(flag);
+ }
+%}
+#endif
+};
+
++and wrapped using: +
+ +
+%{
+#include "flag.h"
+%}
+%include "flag.h"
+
++The second is to use %proxycode within %extend as everything within a %extend block is effectively within the scope of the class, for example: +
+ +
+// flag.h header file
+class Flag {
+ bool flag;
+public:
+ Flag(bool flag) : flag(flag) {}
+ bool FetchFlag() { return flag; }
+};
+
++and wrapped using: +
+ +
+%{
+#include "flag.h"
+%}
+%include "flag.h"
+
+%extend Flag {
+#if defined(SWIG)
+%proxycode %{
+ public String toString() {
+ boolean flag = FetchFlag();
+ return Boolean.toString(flag);
+ }
+%}
+#endif
+}
+
++There is some very limited support of typemaps within a %proxycode block. +A useful trick is to obtain the Java type for a given C/C++ type using the $typemap special macro. +The following C++ template demonstrates this: +
+ +
+%inline %{
+template<typename T> struct Value {
+ T value;
+ Value(const T& val) : value(val) {}
+};
+%}
+
+%extend Value {
+%proxycode %{
+ public String toString() {
+ // Note template type expansion is supported, so T is expanded to 'unsigned int' in this example
+ // and $typemap(jstype, unsigned int) in turn is expanded to 'long'
+ $typemap(jstype, T) val = getValue();
+ return "$javaclassname value: " + val + " Java type: $typemap(jstype, T) JNI type: $typemap(jni, T)";
+ }
+%}
+}
+%template(ValueUnsignedInt) Value<unsigned int>;
+
++The generated Java contains the expanded special variable and macro resulting in Java proxy code: +
+ +
+public class ValueUnsignedInt {
+ ...
+ public String toString() {
+ long val = getValue();
+ return "ValueUnsignedInt value: " + val + " Java type: long JNI type: jlong";
+ }
+
+}
+
+@@ -4522,7 +4660,7 @@ to raise exceptions. See the SWIG Library ch The typemap example Handling C++ exception specifications as Java exceptions provides further exception handling capabilities.
-diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index 8b9aa8257..e5b441fbb 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -3174,6 +3174,7 @@ the module upon loading.
The %insert directive enables inserting blocks of code into a given section of the generated code.
It can be used in one of two ways:
diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk
index e3881afd6..fb5aaa597 100644
--- a/Examples/test-suite/common.mk
+++ b/Examples/test-suite/common.mk
@@ -335,6 +335,7 @@ CPP_TEST_CASES += \
preproc_constants \
primitive_ref \
private_assign \
+ proxycode \
protected_rename \
pure_virtual \
redefined \
diff --git a/Examples/test-suite/csharp/proxycode_runme.cs b/Examples/test-suite/csharp/proxycode_runme.cs
new file mode 100644
index 000000000..24e76c0c6
--- /dev/null
+++ b/Examples/test-suite/csharp/proxycode_runme.cs
@@ -0,0 +1,33 @@
+using System;
+using proxycodeNamespace;
+
+public class proxycode_runme {
+
+ public static void Main() {
+ if (new Proxy1().proxycode1(100) != 101)
+ throw new Exception("Fail");
+ if (new Proxy2().proxycode2a(100) != 102)
+ throw new Exception("Fail");
+ if (new Proxy2().proxycode2b(100) != 102)
+ throw new Exception("Fail");
+ if (new Proxy3().proxycode3(100) != 103)
+ throw new Exception("Fail");
+
+ if (new Proxy4().proxycode4(100) != 104)
+ throw new Exception("Fail");
+ if (new Proxy4.Proxy4Nested().proxycode4nested(100) != 144)
+ throw new Exception("Fail");
+
+ if (new Proxy5a().proxycode5((short)100) != (short)100)
+ throw new Exception("Fail");
+ if (new Proxy5b().proxycode5(100) != 100)
+ throw new Exception("Fail");
+ if (new Proxy5b().proxycode5(100, 100) != 255)
+ throw new Exception("Fail");
+
+ uint t1 = 10;
+ uint t2 = 100;
+ Proxy6 p = new Proxy6().proxyUseT(t1, t2);
+ p.useT(t1, t2);
+ }
+}
diff --git a/Examples/test-suite/d/proxycode_runme.2.d b/Examples/test-suite/d/proxycode_runme.2.d
new file mode 100644
index 000000000..133217f2e
--- /dev/null
+++ b/Examples/test-suite/d/proxycode_runme.2.d
@@ -0,0 +1,41 @@
+module proxycode_runme;
+
+import std.exception;
+import proxycode.Proxy1;
+import proxycode.Proxy2;
+import proxycode.Proxy3;
+import proxycode.Proxy4;
+import proxycode.Proxy5a;
+import proxycode.Proxy5b;
+import proxycode.Proxy6;
+
+void main() {
+ if (new Proxy1().proxycode1(100) != 101)
+ throw new Exception("Fail");
+
+ if (new Proxy1().proxycode1(100) != 101)
+ throw new Exception("Fail");
+ if (new Proxy2().proxycode2a(100) != 102)
+ throw new Exception("Fail");
+ if (new Proxy2().proxycode2b(100) != 102)
+ throw new Exception("Fail");
+ if (new Proxy3().proxycode3(100) != 103)
+ throw new Exception("Fail");
+
+ if (new Proxy4().proxycode4(100) != 104)
+ throw new Exception("Fail");
+// if (new Proxy4.Proxy4Nested().proxycode4nested(100) != 144)
+// throw new Exception("Fail");
+
+ if (new Proxy5a().proxycode5(100) != 100)
+ throw new Exception("Fail");
+ if (new Proxy5b().proxycode5(100) != 100)
+ throw new Exception("Fail");
+ if (new Proxy5b().proxycode5(100, 100) != 255)
+ throw new Exception("Fail");
+
+ uint t1 = 10;
+ uint t2 = 100;
+ Proxy6 p = new Proxy6().proxyUseT(t1, t2);
+ p.useT(t1, t2);
+}
diff --git a/Examples/test-suite/java/proxycode_runme.java b/Examples/test-suite/java/proxycode_runme.java
new file mode 100644
index 000000000..cf981e723
--- /dev/null
+++ b/Examples/test-suite/java/proxycode_runme.java
@@ -0,0 +1,42 @@
+import proxycode.*;
+
+public class proxycode_runme {
+
+ static {
+ try {
+ System.loadLibrary("proxycode");
+ } catch (UnsatisfiedLinkError e) {
+ System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
+ System.exit(1);
+ }
+ }
+
+ public static void main(String argv[]) throws Throwable
+ {
+ if (new Proxy1().proxycode1(100) != 101)
+ throw new RuntimeException("Fail");
+ if (new Proxy2().proxycode2a(100) != 102)
+ throw new RuntimeException("Fail");
+ if (new Proxy2().proxycode2b(100) != 102)
+ throw new RuntimeException("Fail");
+ if (new Proxy3().proxycode3(100) != 103)
+ throw new RuntimeException("Fail");
+
+ if (new Proxy4().proxycode4(100) != 104)
+ throw new RuntimeException("Fail");
+ if (new Proxy4.Proxy4Nested().proxycode4nested(100) != 144)
+ throw new RuntimeException("Fail");
+
+ if (new Proxy5a().proxycode5((short)100) != (short)100)
+ throw new RuntimeException("Fail");
+ if (new Proxy5b().proxycode5(100) != 100)
+ throw new RuntimeException("Fail");
+ if (new Proxy5b().proxycode5(100, 100) != 255)
+ throw new RuntimeException("Fail");
+
+ long t1 = 10;
+ long t2 = 100;
+ Proxy6 p = new Proxy6().proxyUseT(t1, t2);
+ p.useT(t1, t2);
+ }
+}
diff --git a/Examples/test-suite/proxycode.i b/Examples/test-suite/proxycode.i
new file mode 100644
index 000000000..02dab9ade
--- /dev/null
+++ b/Examples/test-suite/proxycode.i
@@ -0,0 +1,141 @@
+%module proxycode
+
+%warnfilter(SWIGWARN_PARSE_NAMED_NESTED_CLASS) Proxy4::Proxy4Nested;
+
+#if defined(SWIGJAVA) || defined(SWIGCSHARP) || defined(SWIGD)
+
+%{
+struct Proxy1 {};
+%}
+struct Proxy1 {
+%proxycode %{
+ public int proxycode1(int i) {
+ return i+1;
+ }
+%}
+};
+
+%proxycode %{
+ this should be ignored as it is not in scope of a class
+%}
+
+%extend Proxy2 {
+%proxycode %{
+ public int proxycode2a(int i) {
+ return i+2;
+ }
+%}
+}
+
+%extend Proxy2 {
+%proxycode %{
+ public int proxycode2b(int i) {
+ return i+2;
+ }
+%}
+}
+
+%inline %{
+struct Proxy2 {};
+struct Proxy3 {};
+struct Proxy4 {
+ struct Proxy4Nested {};
+};
+%}
+
+%extend Proxy3 {
+%proxycode %{
+ public int proxycode3(int i) {
+ return i+3;
+ }
+%}
+}
+
+%extend Proxy4 {
+%proxycode %{
+ public int proxycode4(int i) {
+ return i+4;
+ }
+%}
+}
+%extend Proxy4::Proxy4Nested {
+%proxycode %{
+ public int proxycode4nested(int i) {
+ return i+44;
+ }
+%}
+}
+
+%extend TemplateProxy {
+%proxycode %{
+ public T proxycode5(T i) {
+ return i;
+ }
+%}
+}
+
+%extend TemplateProxy