Add Java support for std::unique<T> for input parameters.
This works by transferring ownership of the underlying C++ memory from the target language proxy class to an instance of the unique_ptr which is passed to the wrapped function via std::move. The proxy class has a new swigRelease() method which sets the underlying C++ pointer for the proxy class to null, so working in much the same way as std::unique_ptr::release(). Any attempt at using the proxy class will be the same as if the delete() function has been called on the proxy class. That is, using a C++ null pointer, when a non-null pointer is usually expected. This commit relies on the previous commit that uses std::move on the temporary variable used for the wrapped function's input parameter as std::unique_ptr is not copyable, it has move-only semantics.
This commit is contained in:
parent
64fa88c0eb
commit
6b361bf050
5 changed files with 94 additions and 1 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL)
|
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL)
|
||||||
|
|
||||||
|
%include "std_string.i"
|
||||||
%include "std_unique_ptr.i"
|
%include "std_unique_ptr.i"
|
||||||
|
|
||||||
%unique_ptr(Klass)
|
%unique_ptr(Klass)
|
||||||
|
|
@ -22,7 +23,7 @@ public:
|
||||||
|
|
||||||
const char* getLabel() const { return m_label.c_str(); }
|
const char* getLabel() const { return m_label.c_str(); }
|
||||||
|
|
||||||
~Klass()
|
virtual ~Klass()
|
||||||
{
|
{
|
||||||
SwigExamples::Lock lock(critical_section);
|
SwigExamples::Lock lock(critical_section);
|
||||||
total_count--;
|
total_count--;
|
||||||
|
|
@ -44,6 +45,24 @@ int Klass::total_count = 0;
|
||||||
|
|
||||||
%inline %{
|
%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<Klass> k) {
|
||||||
|
return std::string(k->getLabel());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool is_nullptr(Klass *p) {
|
||||||
|
return p == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Klass> makeKlassUniquePtr(const char* label) {
|
std::unique_ptr<Klass> makeKlassUniquePtr(const char* label) {
|
||||||
return std::unique_ptr<Klass>(new Klass(label));
|
return std::unique_ptr<Klass>(new Klass(label));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
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");
|
Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first");
|
||||||
if (!k1.getLabel().equals("first"))
|
if (!k1.getLabel().equals("first"))
|
||||||
throw new RuntimeException("wrong object label");
|
throw new RuntimeException("wrong object label");
|
||||||
|
|
|
||||||
|
|
@ -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 %{
|
%inline %{
|
||||||
struct NoExceptTest {
|
struct NoExceptTest {
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,42 @@
|
||||||
* ----------------------------------------------------------------------------- */
|
* ----------------------------------------------------------------------------- */
|
||||||
|
|
||||||
%define %unique_ptr(TYPE)
|
%define %unique_ptr(TYPE)
|
||||||
|
|
||||||
%typemap (jni) std::unique_ptr< TYPE > "jlong"
|
%typemap (jni) std::unique_ptr< TYPE > "jlong"
|
||||||
%typemap (jtype) std::unique_ptr< TYPE > "long"
|
%typemap (jtype) std::unique_ptr< TYPE > "long"
|
||||||
%typemap (jstype) std::unique_ptr< TYPE > "$typemap(jstype, TYPE)"
|
%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 > %{
|
%typemap (out) std::unique_ptr< TYPE > %{
|
||||||
jlong lpp = 0;
|
jlong lpp = 0;
|
||||||
*(TYPE **) &lpp = $1.release();
|
*(TYPE **) &lpp = $1.release();
|
||||||
$result = lpp;
|
$result = lpp;
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%typemap(javaout) std::unique_ptr< TYPE > {
|
%typemap(javaout) std::unique_ptr< TYPE > {
|
||||||
long cPtr = $jnicall;
|
long cPtr = $jnicall;
|
||||||
return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
|
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 >;
|
%template() std::unique_ptr< TYPE >;
|
||||||
%enddef
|
%enddef
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2025,6 +2025,8 @@ public:
|
||||||
typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
|
typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF), // main body of class
|
||||||
NIL);
|
NIL);
|
||||||
|
|
||||||
|
Printv(proxy_class_def, typemapLookup(n, "javarelease", typemap_lookup_type, WARN_NONE), NIL);
|
||||||
|
|
||||||
// C++ destructor is wrapped by the delete method
|
// C++ destructor is wrapped by the delete method
|
||||||
// Note that the method name is specified in a typemap attribute called methodname
|
// Note that the method name is specified in a typemap attribute called methodname
|
||||||
String *destruct = NewString("");
|
String *destruct = NewString("");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue