diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 9bd65b97f..fd0e8e942 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -2,6 +2,7 @@ #if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) +%include "std_string.i" %include "std_unique_ptr.i" %unique_ptr(Klass) @@ -22,7 +23,7 @@ public: const char* getLabel() const { return m_label.c_str(); } - ~Klass() + virtual ~Klass() { SwigExamples::Lock lock(critical_section); total_count--; @@ -44,6 +45,24 @@ int Klass::total_count = 0; %inline %{ +// Virtual inheritance used as this usually results in different values for Klass* and KlassInheritance* +// for testing class inheritance and unique_ptr +struct KlassInheritance : virtual Klass { + KlassInheritance(const char* label) : Klass(label) { + // std::cout << "ptrs.... " << std::hex << (Klass*)this << " " << (KlassInheritance*)this << std::endl; + } +}; + +#if defined(SWIGJAVA) +std::string takeKlassUniquePtr(std::unique_ptr k) { + return std::string(k->getLabel()); +} +#endif + +bool is_nullptr(Klass *p) { + return p == nullptr; +} + std::unique_ptr makeKlassUniquePtr(const char* label) { return std::unique_ptr(new Klass(label)); } diff --git a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java index a734b0e5e..3f2b15f44 100644 --- a/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java +++ b/Examples/test-suite/java/cpp11_std_unique_ptr_runme.java @@ -20,8 +20,42 @@ public class cpp11_std_unique_ptr_runme { } } + private static void checkCount(int expected_count) { + int actual_count = Klass.getTotal_count(); + if (actual_count != expected_count) + throw new RuntimeException("Counts incorrect, expected:" + expected_count + " actual:" + actual_count); + } + public static void main(String argv[]) throws Throwable { + // unique_ptr as input + { + Klass kin = new Klass("KlassInput"); + checkCount(1); + String s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin); + checkCount(0); + if (!s.equals("KlassInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kin)) + throw new RuntimeException("is_nullptr failed"); + kin.delete(); // Should not fail, even though already deleted + checkCount(0); + } + + { + KlassInheritance kini = new KlassInheritance("KlassInheritanceInput"); + checkCount(1); + String s = cpp11_std_unique_ptr.takeKlassUniquePtr(kini); + checkCount(0); + if (!s.equals("KlassInheritanceInput")) + throw new RuntimeException("Incorrect string: " + s); + if (!cpp11_std_unique_ptr.is_nullptr(kini)) + throw new RuntimeException("is_nullptr failed"); + kini.delete(); // Should not fail, even though already deleted + checkCount(0); + } + + // unique_ptr as output Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first"); if (!k1.getLabel().equals("first")) throw new RuntimeException("wrong object label"); diff --git a/Examples/test-suite/java_throws.i b/Examples/test-suite/java_throws.i index 6cd47b448..940f2c192 100644 --- a/Examples/test-suite/java_throws.i +++ b/Examples/test-suite/java_throws.i @@ -192,6 +192,21 @@ try { } } %} +%typemap(javarelease) SWIGTYPE %{ + protected static long swigRelease($javaclassname obj) { + long ptr = 0; + if (obj != null) { + ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + try { + obj.delete(); + } catch (MyException e) { + throw new RuntimeException(e); + } + } + return ptr; + } +%} %inline %{ struct NoExceptTest { diff --git a/Lib/java/std_unique_ptr.i b/Lib/java/std_unique_ptr.i index 665d913ae..7a647f616 100644 --- a/Lib/java/std_unique_ptr.i +++ b/Lib/java/std_unique_ptr.i @@ -8,19 +8,42 @@ * ----------------------------------------------------------------------------- */ %define %unique_ptr(TYPE) + %typemap (jni) std::unique_ptr< TYPE > "jlong" %typemap (jtype) std::unique_ptr< TYPE > "long" %typemap (jstype) std::unique_ptr< TYPE > "$typemap(jstype, TYPE)" +%typemap(in) std::unique_ptr< TYPE > (TYPE *unique_temp) +%{ unique_temp = *(TYPE **)&$input; + $1.reset(unique_temp); %} + +%typemap(javain) std::unique_ptr< TYPE > "$typemap(jstype, TYPE).swigRelease($javainput)" + %typemap (out) std::unique_ptr< TYPE > %{ jlong lpp = 0; *(TYPE **) &lpp = $1.release(); $result = lpp; %} + %typemap(javaout) std::unique_ptr< TYPE > { long cPtr = $jnicall; return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true); } + +%typemap(javarelease) TYPE %{ + protected static long swigRelease($javaclassname obj) { + long ptr = 0; + if (obj != null) { + if (!obj.swigCMemOwn) + throw new RuntimeException("Cannot release ownership as memory is not owned"); + ptr = obj.swigCPtr; + obj.swigCMemOwn = false; + obj.delete(); + } + return ptr; + } +%} + %template() std::unique_ptr< TYPE >; %enddef diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx index ea7e4607a..cf39fc80b 100644 --- a/Source/Modules/java.cxx +++ b/Source/Modules/java.cxx @@ -2025,6 +2025,8 @@ public: typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class NIL); + Printv(proxy_class_def, typemapLookup(n, "javarelease", typemap_lookup_type, WARN_NONE), NIL); + // C++ destructor is wrapped by the delete method // Note that the method name is specified in a typemap attribute called methodname String *destruct = NewString("");