Merge branch 'unique_ptr-inputs'

* unique_ptr-inputs:
  std::unique_ptr std::auto_ptr tidyup
  Add support for std::auto_ptr inputs
  Cosmetic formatting and doc updates in std_unique_ptr.i files
  Add Perl support for std::unique_ptr inputs
  Add Ruby support for std::unique_ptr inputs
  Add Python support for std::unique_ptr inputs
  Add C# support std::unique_ptr inputs
  Java unique_ptr test ownership enhancement to test
  Java unique_ptr enhance test for double release
  SWIGTYPE && input typemaps now assume object has been moved
  Add Java support for std::unique<T> for input parameters.

Closes #692

Conflicts:
	CHANGES.current
This commit is contained in:
William S Fulton 2022-07-19 20:26:18 +01:00
commit 8b654afdef
37 changed files with 1291 additions and 116 deletions

View File

@ -7,6 +7,14 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress)
===========================
2022-07-19: wsfulton
#692 [C#, Java, Perl, Python, Ruby] std::unique_ptr and std::auto_ptr typemaps
provided for inputs types in std_unique_ptr.i and std_auto_ptr.i.
Now these smart pointers can be used as input parameters to functions. A proxy
class instance transfers memory ownership of the underlying C++ object from the
proxy class to a smart pointer instance passed to the wrapped function.
2022-07-19: jschueller
[Python] #2314 Drop support for Python 3.2.

View File

@ -2055,13 +2055,9 @@ equivalent <tt>%shared_ptr(T)</tt> macro covered in the previous section.
</p>
<p>
Note that the support provided is limited to returning this smart pointer from a function.
Any other use of <tt>std::auto_ptr</tt> is not directly provided yet.
Example usage of a <tt>std::unique_ptr</tt> being returned from a function is shown below.
</p>
<p>
Example usage would be
</p>
<div class="code">
<pre>
%include &lt;std_unique_ptr.i&gt;
@ -2113,12 +2109,67 @@ Note that the implementation is quite different to the <tt>std::shared_ptr</tt>
where the proxy class manages the underlying C++ memory as a pointer to a shared_ptr instead of a plain raw pointer.
</p>
<p>
A possibly less common usage of this smart pointer is as a parameter to a function.
When used like this it indicates that memory usage of the object pointed to by the underlying pointer
is transferred to the function being called.
The code that SWIG generates assumes this happens.
First, it is assumed that a proxy class already owns the underlying C++ object and is used to pass the object to the C++ function being called.
Second, the ownership is transferred from the proxy class to the C++ function being called and
lifetime is then controlled by the function.
Finally, it is assumed the lifetime of the object may not last beyond returning from the C++ function
and hence the proxy class can no longer be used.
</p>
<p>
Consider expanding the example above with a function that takes a <tt>std::unique_ptr</tt> as follows:
</p>
<div class="code">
<pre>
void take(std::unique_ptr<Klass>);
</pre>
</div>
<p>
and use from C#:
</p>
<div class="targetlang">
<pre>
Klass k = Klass.Create(17); // create an instance of Klass any way you like
int value = k.getValue(); // ok
example.take(k); // memory ownership passes from C# layer to C++ layer
int v = k.getValue(); // don't do this - invalid use of k
</pre>
</div>
<p>
Attempts to use <tt>k</tt> after the ownership has been passed into the <tt>take</tt> function
should not be attempted.
The implementation sets the proxy class to an invalid state by setting the class's underlying
C++ pointer to null after the return from the <tt>take</tt> function.
Subsequent use of an invalid proxy class instance is very much dependent on the implementation
in the target language and ranges from a segfault to giving a nice error.
Consider implementing additional checks via the 'check' typemap.
</p>
<p>
Attempts to pass ownership from a proxy class to a <tt>std::unique</tt> parameter more than once will result
in a "Cannot release ownership as memory is not owned" exception. For example, if <tt>example.take(k)</tt> in the example above is called twice.
</p>
<p>
<b>Compatibility note:</b> Support for <tt>std::unique_ptr</tt> was added in SWIG-4.1.0.
</p>
<H3><a name="Library_std_auto_ptr">12.4.6 auto_ptr smart pointer</a></H3>
<p>
While <tt>std::auto_ptr</tt> is deprecated in C++11, some existing code may
still be using it, so SWIG provides limited support for this class by some target languages.
still be using it. SWIG provides support for this class which is nearly identical
to <tt>std::unique_ptr</tt>.
</p>
<p>
@ -2133,13 +2184,9 @@ the previous two sections.
</p>
<p>
Note that the support provided is limited to returning this smart pointer from a function.
Any other use of <tt>std::auto_ptr</tt> is not directly provided.
Example usage of a <tt>std::auto_ptr</tt> being returned from a function is shown below.
</p>
<p>
Example usage would be
</p>
<div class="code">
<pre>
%include &lt;std_auto_ptr.i&gt;
@ -2181,6 +2228,10 @@ The implementation simply calls <tt>std::auto_ptr::release()</tt> to obtain the
That is, it works the same way covered in the previous section for <tt>std::unique_ptr</tt>.
</p>
<p>
Input parameters also work the same way as <tt>std::unique_ptr</tt> covered in the previous section.
</p>
<H2><a name="Library_nn16">12.5 Utility Libraries</a></H2>

View File

@ -610,6 +610,7 @@ CPP11_TEST_CASES += \
cpp11_rvalue_reference \
cpp11_rvalue_reference2 \
cpp11_rvalue_reference3 \
cpp11_rvalue_reference_move_input \
cpp11_sizeof_object \
cpp11_static_assert \
cpp11_std_array \

View File

@ -0,0 +1,41 @@
%module cpp11_rvalue_reference_move_input
// Testcase for testing rvalue reference input typemaps which assume the object is moved during a function call
#if defined(SWIGD)
%rename(trace) debug;
#endif
%include "cpp11_move_only_helper.i"
%rename(MoveAssign) MovableCopyable::operator=(MovableCopyable &&);
%ignore MovableCopyable::operator=(const MovableCopyable &); // ignore copy assignment operator, keep move assignment operator
%ignore MovableCopyable::MovableCopyable(const MovableCopyable &); // ignore copy constructor, keep the move constructor
%inline %{
#include <iostream>
using namespace std;
bool debug = false;
class MovableCopyable {
public:
MovableCopyable(int i = 0) { if (debug) cout << "MovableCopyable(" << i << ")" << " " << this << endl; Counter::normal_constructor++; }
MovableCopyable(const MovableCopyable &other) { if (debug) cout << "MovableCopyable(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_constructor++;}
MovableCopyable & operator=(const MovableCopyable &other) { if (debug) cout << "operator=(const MovableCopyable &)" << " " << this << " " << &other << endl; Counter::copy_assignment++; return *this; }
MovableCopyable(MovableCopyable &&other) noexcept { if (debug) cout << "MovableCopyable(MovableCopyable &&)" << " " << this << endl; Counter::move_constructor++; }
MovableCopyable & operator=(MovableCopyable &&other) noexcept { if (debug) cout << "operator=(MovableCopyable &&)" << " " << this << endl; Counter::move_assignment++; return *this; }
~MovableCopyable() { if (debug) cout << "~MovableCopyable()" << " " << this << endl; Counter::destructor++; }
static void movein(MovableCopyable &&mcin) {
MovableCopyable mc = std::move(mcin);
}
static bool is_nullptr(MovableCopyable *p) {
return p == nullptr;
}
};
%}

View File

@ -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,26 @@ 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;
}
};
std::string takeKlassUniquePtr(std::unique_ptr<Klass> k) {
return std::string(k->getLabel());
}
bool is_nullptr(Klass *p) {
return p == nullptr;
}
Klass *get_not_owned_ptr(Klass *p) {
return p;
}
std::unique_ptr<Klass> makeKlassUniquePtr(const char* label) {
return std::unique_ptr<Klass>(new Klass(label));
}

View File

@ -9,8 +9,75 @@ public class cpp11_std_unique_ptr_runme {
System.Threading.Thread.Sleep(10);
}
private static void checkCount(int expected_count)
{
int actual_count = Klass.getTotal_count();
if (actual_count != expected_count)
throw new ApplicationException("Counts incorrect, expected:" + expected_count + " actual:" + actual_count);
}
public static void Main()
{
// unique_ptr as input
using (Klass kin = new Klass("KlassInput")) {
checkCount(1);
string s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin);
checkCount(0);
if (s != "KlassInput")
throw new ApplicationException("Incorrect string: " + s);
if (!cpp11_std_unique_ptr.is_nullptr(kin))
throw new ApplicationException("is_nullptr failed");
} // Dispose should not fail, even though already deleted
checkCount(0);
using (Klass kin = new Klass("KlassInput")) {
checkCount(1);
string s = cpp11_std_unique_ptr.takeKlassUniquePtr(kin);
checkCount(0);
if (s != "KlassInput")
throw new ApplicationException("Incorrect string: " + s);
if (!cpp11_std_unique_ptr.is_nullptr(kin))
throw new ApplicationException("is_nullptr failed");
bool exception_thrown = false;
try {
cpp11_std_unique_ptr.takeKlassUniquePtr(kin);
} catch (ApplicationException e) {
if (!e.Message.Contains("Cannot release ownership as memory is not owned"))
throw new ApplicationException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new ApplicationException("double usage of takeKlassUniquePtr should have been an error");
} // Dispose should not fail, even though already deleted
checkCount(0);
using (Klass kin = new Klass("KlassInput")) {
bool exception_thrown = false;
try {
Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin);
cpp11_std_unique_ptr.takeKlassUniquePtr(notowned);
} catch (ApplicationException e) {
if (!e.Message.Contains("Cannot release ownership as memory is not owned"))
throw new ApplicationException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error");
}
checkCount(0);
using (KlassInheritance kini = new KlassInheritance("KlassInheritanceInput")) {
checkCount(1);
string s = cpp11_std_unique_ptr.takeKlassUniquePtr(kini);
checkCount(0);
if (s != "KlassInheritanceInput")
throw new ApplicationException("Incorrect string: " + s);
if (!cpp11_std_unique_ptr.is_nullptr(kini))
throw new ApplicationException("is_nullptr failed");
} // Dispose should not fail, even though already deleted
checkCount(0);
// unique_ptr as output
Klass k1 = cpp11_std_unique_ptr.makeKlassUniquePtr("first");
if (k1.getLabel() != "first")
throw new Exception("wrong object label");

View File

@ -9,8 +9,75 @@ public class li_std_auto_ptr_runme {
System.Threading.Thread.Sleep(10);
}
private static void checkCount(int expected_count)
{
int actual_count = Klass.getTotal_count();
if (actual_count != expected_count)
throw new ApplicationException("Counts incorrect, expected:" + expected_count + " actual:" + actual_count);
}
public static void Main()
{
// auto_ptr as input
using (Klass kin = new Klass("KlassInput")) {
checkCount(1);
string s = li_std_auto_ptr.takeKlassAutoPtr(kin);
checkCount(0);
if (s != "KlassInput")
throw new ApplicationException("Incorrect string: " + s);
if (!li_std_auto_ptr.is_nullptr(kin))
throw new ApplicationException("is_nullptr failed");
} // Dispose should not fail, even though already deleted
checkCount(0);
using (Klass kin = new Klass("KlassInput")) {
checkCount(1);
string s = li_std_auto_ptr.takeKlassAutoPtr(kin);
checkCount(0);
if (s != "KlassInput")
throw new ApplicationException("Incorrect string: " + s);
if (!li_std_auto_ptr.is_nullptr(kin))
throw new ApplicationException("is_nullptr failed");
bool exception_thrown = false;
try {
li_std_auto_ptr.takeKlassAutoPtr(kin);
} catch (ApplicationException e) {
if (!e.Message.Contains("Cannot release ownership as memory is not owned"))
throw new ApplicationException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new ApplicationException("double usage of takeKlassAutoPtr should have been an error");
} // Dispose should not fail, even though already deleted
checkCount(0);
using (Klass kin = new Klass("KlassInput")) {
bool exception_thrown = false;
try {
Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin);
li_std_auto_ptr.takeKlassAutoPtr(notowned);
} catch (ApplicationException e) {
if (!e.Message.Contains("Cannot release ownership as memory is not owned"))
throw new ApplicationException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new ApplicationException("Should have thrown 'Cannot release ownership as memory is not owned' error");
}
checkCount(0);
using (KlassInheritance kini = new KlassInheritance("KlassInheritanceInput")) {
checkCount(1);
string s = li_std_auto_ptr.takeKlassAutoPtr(kini);
checkCount(0);
if (s != "KlassInheritanceInput")
throw new ApplicationException("Incorrect string: " + s);
if (!li_std_auto_ptr.is_nullptr(kini))
throw new ApplicationException("is_nullptr failed");
} // Dispose should not fail, even though already deleted
checkCount(0);
// auto_ptr as output
Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first");
if (k1.getLabel() != "first")
throw new Exception("wrong object label");

View File

@ -0,0 +1,60 @@
import cpp11_rvalue_reference_move_input.*;
public class cpp11_rvalue_reference_move_input_runme {
static {
try {
System.loadLibrary("cpp11_rvalue_reference_move_input");
} 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[]) {
{
Counter.reset_counts();
MovableCopyable mo = new MovableCopyable(222);
Counter.check_counts(1, 0, 0, 0, 0, 0);
MovableCopyable.movein(mo);
Counter.check_counts(1, 0, 0, 1, 0, 2);
if (!MovableCopyable.is_nullptr(mo))
throw new RuntimeException("is_nullptr failed");
mo.delete();
Counter.check_counts(1, 0, 0, 1, 0, 2);
}
{
// Move constructor test
Counter.reset_counts();
MovableCopyable mo = new MovableCopyable(222);
Counter.check_counts(1, 0, 0, 0, 0, 0);
MovableCopyable mo_moved = new MovableCopyable(mo);
Counter.check_counts(1, 0, 0, 1, 0, 1);
if (!MovableCopyable.is_nullptr(mo))
throw new RuntimeException("is_nullptr failed");
mo.delete();
Counter.check_counts(1, 0, 0, 1, 0, 1);
mo_moved.delete();
Counter.check_counts(1, 0, 0, 1, 0, 2);
}
{
// Move assignment operator test
Counter.reset_counts();
MovableCopyable mo111 = new MovableCopyable(111);
MovableCopyable mo222 = new MovableCopyable(222);
Counter.check_counts(2, 0, 0, 0, 0, 0);
mo111.MoveAssign(mo222);
Counter.check_counts(2, 0, 0, 0, 1, 1);
if (!MovableCopyable.is_nullptr(mo222))
throw new RuntimeException("is_nullptr failed");
mo222.delete();
Counter.check_counts(2, 0, 0, 0, 1, 1);
mo111.delete();
Counter.check_counts(2, 0, 0, 0, 1, 2);
}
}
}

View File

@ -20,8 +20,82 @@ 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);
}
{
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");
boolean exception_thrown = false;
try {
cpp11_std_unique_ptr.takeKlassUniquePtr(kin);
} catch (RuntimeException e) {
if (!e.getMessage().contains("Cannot release ownership as memory is not owned"))
throw new RuntimeException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new RuntimeException("double usage of takeKlassUniquePtr should have been an error");
kin.delete(); // Should not fail, even though already deleted
checkCount(0);
}
{
Klass kin = new Klass("KlassInput");
boolean exception_thrown = false;
try {
Klass notowned = cpp11_std_unique_ptr.get_not_owned_ptr(kin);
cpp11_std_unique_ptr.takeKlassUniquePtr(notowned);
} catch (RuntimeException e) {
if (!e.getMessage().contains("Cannot release ownership as memory is not owned"))
throw new RuntimeException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error");
kin.delete();
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");

View File

@ -20,8 +20,82 @@ public class li_std_auto_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
{
// auto_ptr as input
{
Klass kin = new Klass("KlassInput");
checkCount(1);
String s = li_std_auto_ptr.takeKlassAutoPtr(kin);
checkCount(0);
if (!s.equals("KlassInput"))
throw new RuntimeException("Incorrect string: " + s);
if (!li_std_auto_ptr.is_nullptr(kin))
throw new RuntimeException("is_nullptr failed");
kin.delete(); // Should not fail, even though already deleted
checkCount(0);
}
{
Klass kin = new Klass("KlassInput");
checkCount(1);
String s = li_std_auto_ptr.takeKlassAutoPtr(kin);
checkCount(0);
if (!s.equals("KlassInput"))
throw new RuntimeException("Incorrect string: " + s);
if (!li_std_auto_ptr.is_nullptr(kin))
throw new RuntimeException("is_nullptr failed");
boolean exception_thrown = false;
try {
li_std_auto_ptr.takeKlassAutoPtr(kin);
} catch (RuntimeException e) {
if (!e.getMessage().contains("Cannot release ownership as memory is not owned"))
throw new RuntimeException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new RuntimeException("double usage of takeKlassAutoPtr should have been an error");
kin.delete(); // Should not fail, even though already deleted
checkCount(0);
}
{
Klass kin = new Klass("KlassInput");
boolean exception_thrown = false;
try {
Klass notowned = li_std_auto_ptr.get_not_owned_ptr(kin);
li_std_auto_ptr.takeKlassAutoPtr(notowned);
} catch (RuntimeException e) {
if (!e.getMessage().contains("Cannot release ownership as memory is not owned"))
throw new RuntimeException("incorrect exception message");
exception_thrown = true;
}
if (!exception_thrown)
throw new RuntimeException("Should have thrown 'Cannot release ownership as memory is not owned' error");
kin.delete();
checkCount(0);
}
{
KlassInheritance kini = new KlassInheritance("KlassInheritanceInput");
checkCount(1);
String s = li_std_auto_ptr.takeKlassAutoPtr(kini);
checkCount(0);
if (!s.equals("KlassInheritanceInput"))
throw new RuntimeException("Incorrect string: " + s);
if (!li_std_auto_ptr.is_nullptr(kini))
throw new RuntimeException("is_nullptr failed");
kini.delete(); // Should not fail, even though already deleted
checkCount(0);
}
// auto_ptr as output
Klass k1 = li_std_auto_ptr.makeKlassAutoPtr("first");
if (!k1.getLabel().equals("first"))
throw new RuntimeException("wrong object label");

View File

@ -193,6 +193,37 @@ try {
}
%}
%typemap(javabody) SWIGTYPE %{
private transient long swigCPtr;
protected transient boolean swigCMemOwn;
protected $javaclassname(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
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;
try {
obj.delete();
} catch (MyException e) {
throw new RuntimeException(e);
}
}
return ptr;
}
%}
%inline %{
struct NoExceptTest {
unsigned int noExceptionPlease() { return 123; }

View File

@ -14,6 +14,7 @@
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL)
%include "std_string.i"
%include "std_auto_ptr.i"
%auto_ptr(Klass)
@ -27,10 +28,13 @@ namespace std {
template <class T> class auto_ptr {
T *ptr;
public:
auto_ptr(T *ptr = 0) : ptr(ptr) {}
explicit auto_ptr(T *p = 0) : ptr(p) {}
auto_ptr(auto_ptr&& a) : ptr(a.ptr) { a.ptr = 0;}
~auto_ptr() { delete ptr; }
T *release() { T *p = ptr; ptr = 0; return p; }
void reset(T *p = 0) { delete ptr; ptr = p; }
T &operator*() const { return *ptr; }
T *operator->() const { return ptr; }
auto_ptr& operator=(auto_ptr&& a) { if (&a != this) { delete ptr; ptr = a.ptr; a.ptr = 0; } return *this; }
};
}
@ -53,7 +57,7 @@ public:
const char* getLabel() const { return m_label.c_str(); }
~Klass()
virtual ~Klass()
{
SwigExamples::Lock lock(critical_section);
total_count--;
@ -73,10 +77,28 @@ int Klass::total_count = 0;
%}
%template(KlassAutoPtr) std::auto_ptr<Klass>;
%inline %{
// Virtual inheritance used as this usually results in different values for Klass* and KlassInheritance*
// for testing class inheritance and auto_ptr
struct KlassInheritance : virtual Klass {
KlassInheritance(const char* label) : Klass(label) {
// std::cout << "ptrs.... " << std::hex << (Klass*)this << " " << (KlassInheritance*)this << std::endl;
}
};
std::string takeKlassAutoPtr(std::auto_ptr<Klass> k) {
return std::string(k->getLabel());
}
bool is_nullptr(Klass *p) {
return p == 0;
}
Klass *get_not_owned_ptr(Klass *p) {
return p;
}
std::auto_ptr<Klass> makeKlassAutoPtr(const char* label) {
return std::auto_ptr<Klass>(new Klass(label));
}

View File

@ -1,9 +1,67 @@
use strict;
use warnings;
use Test::More tests => 6;
use Test::More tests => 24;
BEGIN { use_ok('cpp11_std_unique_ptr') }
require_ok('cpp11_std_unique_ptr');
# adapted from ../java/cpp11_std_unique_ptr_runme.java
sub checkCount {
my($expected_count) = @_;
my $actual_count = cpp11_std_unique_ptr::Klass::getTotal_count();
is($actual_count, $expected_count, "Counts incorrect, expected: $expected_count actual: $actual_count");
}
# unique_ptr as input
{
my $kin = new cpp11_std_unique_ptr::Klass("KlassInput");
checkCount(1);
my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kin);
checkCount(0);
is($s, "KlassInput", "Incorrect string: $s");
is(cpp11_std_unique_ptr::is_nullptr($kin), 1, "is_nullptr check");
undef $kin; # Should not fail, even though already deleted
checkCount(0);
}
{
my $kin = new cpp11_std_unique_ptr::Klass("KlassInput");
checkCount(1);
my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kin);
checkCount(0);
is($s, "KlassInput", "Incorrect string: $s");
is(cpp11_std_unique_ptr::is_nullptr($kin), 1, "is_nullptr check");
eval {
cpp11_std_unique_ptr::takeKlassUniquePtr($kin);
};
like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassUniquePtr should be an error");
undef $kin; # Should not fail, even though already deleted
checkCount(0);
}
{
my $kin = new cpp11_std_unique_ptr::Klass("KlassInput");
eval {
my $notowned = cpp11_std_unique_ptr::get_not_owned_ptr($kin);
cpp11_std_unique_ptr::takeKlassUniquePtr($notowned);
};
like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassUniquePtr should be an error");
undef $kin;
checkCount(0);
}
{
my $kini = new cpp11_std_unique_ptr::KlassInheritance("KlassInheritanceInput");
checkCount(1);
my $s = cpp11_std_unique_ptr::takeKlassUniquePtr($kini);
checkCount(0);
is($s, "KlassInheritanceInput", "Incorrect string: $s");
is(cpp11_std_unique_ptr::is_nullptr($kini), 1, "is_nullptr failed");
undef $kini; # Should not fail, even though already deleted
checkCount(0);
}
# unique_ptr as output
my $k1 = cpp11_std_unique_ptr::makeKlassUniquePtr("first");
my $k2 = cpp11_std_unique_ptr::makeKlassUniquePtr("second");
is(cpp11_std_unique_ptr::Klass::getTotal_count, 2, "have 2 pointers");

View File

@ -1,9 +1,67 @@
use strict;
use warnings;
use Test::More tests => 6;
use Test::More tests => 24;
BEGIN { use_ok('li_std_auto_ptr') }
require_ok('li_std_auto_ptr');
# adapted from ../java/li_std_auto_ptr_runme.java
sub checkCount {
my($expected_count) = @_;
my $actual_count = li_std_auto_ptr::Klass::getTotal_count();
is($actual_count, $expected_count, "Counts incorrect, expected: $expected_count actual: $actual_count");
}
# auto_ptr as input
{
my $kin = new li_std_auto_ptr::Klass("KlassInput");
checkCount(1);
my $s = li_std_auto_ptr::takeKlassAutoPtr($kin);
checkCount(0);
is($s, "KlassInput", "Incorrect string: $s");
is(li_std_auto_ptr::is_nullptr($kin), 1, "is_nullptr check");
undef $kin; # Should not fail, even though already deleted
checkCount(0);
}
{
my $kin = new li_std_auto_ptr::Klass("KlassInput");
checkCount(1);
my $s = li_std_auto_ptr::takeKlassAutoPtr($kin);
checkCount(0);
is($s, "KlassInput", "Incorrect string: $s");
is(li_std_auto_ptr::is_nullptr($kin), 1, "is_nullptr check");
eval {
li_std_auto_ptr::takeKlassAutoPtr($kin);
};
like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassAutoPtr should be an error");
undef $kin; # Should not fail, even though already deleted
checkCount(0);
}
{
my $kin = new li_std_auto_ptr::Klass("KlassInput");
eval {
my $notowned = li_std_auto_ptr::get_not_owned_ptr($kin);
li_std_auto_ptr::takeKlassAutoPtr($notowned);
};
like($@, qr/\bcannot release ownership as memory is not owned\b/, "double usage of takeKlassAutoPtr should be an error");
undef $kin;
checkCount(0);
}
{
my $kini = new li_std_auto_ptr::KlassInheritance("KlassInheritanceInput");
checkCount(1);
my $s = li_std_auto_ptr::takeKlassAutoPtr($kini);
checkCount(0);
is($s, "KlassInheritanceInput", "Incorrect string: $s");
is(li_std_auto_ptr::is_nullptr($kini), 1, "is_nullptr failed");
undef $kini; # Should not fail, even though already deleted
checkCount(0);
}
# auto_ptr as output
my $k1 = li_std_auto_ptr::makeKlassAutoPtr("first");
my $k2 = li_std_auto_ptr::makeKlassAutoPtr("second");
is(li_std_auto_ptr::Klass::getTotal_count, 2, "have 2 pointers");

View File

@ -1,5 +1,72 @@
from cpp11_std_unique_ptr import *
def checkCount(expected_count):
actual_count = Klass.getTotal_count()
if (actual_count != expected_count):
raise RuntimeError("Counts incorrect, expected:" + expected_count + " actual:" + actual_count)
# unique_ptr as input
kin = Klass("KlassInput")
checkCount(1)
s = takeKlassUniquePtr(kin)
checkCount(0)
if kin.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kin):
raise RuntimeError("is_nullptr failed")
del kin # Should not fail, even though already deleted
checkCount(0)
kin = Klass("KlassInput")
checkCount(1)
s = takeKlassUniquePtr(kin)
checkCount(0)
if kin.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kin):
raise RuntimeError("is_nullptr failed")
exception_thrown = False
try:
s = takeKlassUniquePtr(kin)
except RuntimeError as e:
if "cannot release ownership as memory is not owned" not in str(e):
raise RuntimeError("incorrect exception message");
exception_thrown = True
if not exception_thrown:
raise RuntimeError("double usage of takeKlassUniquePtr should have been an error")
del kin # Should not fail, even though already deleted
checkCount(0)
kin = Klass("KlassInput")
exception_thrown = False
try:
notowned = get_not_owned_ptr(kin)
takeKlassUniquePtr(notowned)
except RuntimeError as e:
exception_thrown = True
if not exception_thrown:
raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error")
del kin
checkCount(0)
kini = KlassInheritance("KlassInheritanceInput")
checkCount(1)
s = takeKlassUniquePtr(kini)
checkCount(0)
if kini.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInheritanceInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kini):
raise RuntimeError("is_nullptr failed")
del kini # Should not fail, even though already deleted
checkCount(0)
# unique_ptr as output
k1 = makeKlassUniquePtr("first")
k2 = makeKlassUniquePtr("second")
if Klass.getTotal_count() != 2:

View File

@ -1,5 +1,72 @@
from li_std_auto_ptr import *
def checkCount(expected_count):
actual_count = Klass.getTotal_count()
if (actual_count != expected_count):
raise RuntimeError("Counts incorrect, expected:" + expected_count + " actual:" + actual_count)
# auto_ptr as input
kin = Klass("KlassInput")
checkCount(1)
s = takeKlassAutoPtr(kin)
checkCount(0)
if kin.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kin):
raise RuntimeError("is_nullptr failed")
del kin # Should not fail, even though already deleted
checkCount(0)
kin = Klass("KlassInput")
checkCount(1)
s = takeKlassAutoPtr(kin)
checkCount(0)
if kin.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kin):
raise RuntimeError("is_nullptr failed")
exception_thrown = False
try:
s = takeKlassAutoPtr(kin)
except RuntimeError as e:
if "cannot release ownership as memory is not owned" not in str(e):
raise RuntimeError("incorrect exception message");
exception_thrown = True
if not exception_thrown:
raise RuntimeError("double usage of takeKlassAutoPtr should have been an error")
del kin # Should not fail, even though already deleted
checkCount(0)
kin = Klass("KlassInput")
exception_thrown = False
try:
notowned = get_not_owned_ptr(kin)
takeKlassAutoPtr(notowned)
except RuntimeError as e:
exception_thrown = True
if not exception_thrown:
raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error")
del kin
checkCount(0)
kini = KlassInheritance("KlassInheritanceInput")
checkCount(1)
s = takeKlassAutoPtr(kini)
checkCount(0)
if kini.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInheritanceInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kini):
raise RuntimeError("is_nullptr failed")
del kini # Should not fail, even though already deleted
checkCount(0)
# auto_ptr as output
k1 = makeKlassAutoPtr("first")
k2 = makeKlassAutoPtr("second")
if Klass.getTotal_count() != 2:

View File

@ -11,6 +11,100 @@ def gc_check(expected_count)
# swig_assert_equal_simple(expected_count, Cpp11_std_unique_ptr::Klass::getTotal_count())
end
def checkCount(expected_count)
actual_count = Cpp11_std_unique_ptr::Klass.getTotal_count()
if (actual_count != expected_count)
raise RuntimeError, "Counts incorrect, expected:" + expected_count + " actual:" + actual_count
end
end
# unique_ptr as input
kin = Cpp11_std_unique_ptr::Klass.new("KlassInput")
checkCount(1)
s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kin)
checkCount(0)
if (s != "KlassInput")
raise RuntimeError, "Incorrect string: " + s
end
exception_thrown = false
begin
Cpp11_std_unique_ptr.is_nullptr(kin)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
kin = nil
checkCount(0)
kin = Cpp11_std_unique_ptr::Klass.new("KlassInput")
checkCount(1)
s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kin)
checkCount(0)
if (s != "KlassInput")
raise RuntimeError, "Incorrect string: " + s
end
exception_thrown = false
begin
Cpp11_std_unique_ptr.is_nullptr(kin)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
exception_thrown = false
begin
Cpp11_std_unique_ptr.takeKlassUniquePtr(kin)
rescue RuntimeError => e
# puts e.message
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "double usage of takeKlassUniquePtr should have been an error"
end
kin = nil
checkCount(0)
kin = Cpp11_std_unique_ptr::Klass.new("KlassInput")
exception_thrown = false
begin
notowned = Cpp11_std_unique_ptr::get_not_owned_ptr(kin)
Cpp11_std_unique_ptr::takeKlassUniquePtr(notowned)
rescue RuntimeError => e
if (!e.to_s.include? "cannot release ownership as memory is not owned")
raise RuntimeError, "incorrect exception message"
end
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error"
end
Cpp11_std_unique_ptr.takeKlassUniquePtr(kin) # Ensure object is deleted (can't rely on GC)
checkCount(0)
kini = Cpp11_std_unique_ptr::KlassInheritance.new("KlassInheritanceInput")
checkCount(1)
s = Cpp11_std_unique_ptr.takeKlassUniquePtr(kini)
checkCount(0)
if (s != "KlassInheritanceInput")
raise RuntimeError, "Incorrect string: " + s
end
exception_thrown = false
begin
Cpp11_std_unique_ptr.is_nullptr(kini)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
kini = nil
checkCount(0)
# unique_ptr as output
k1 = Cpp11_std_unique_ptr::makeKlassUniquePtr("first")
k2 = Cpp11_std_unique_ptr::makeKlassUniquePtr("second")
swig_assert_equal_simple(2, Cpp11_std_unique_ptr::Klass::getTotal_count())

View File

@ -11,6 +11,100 @@ def gc_check(expected_count)
# swig_assert_equal_simple(expected_count, Li_std_auto_ptr::Klass::getTotal_count())
end
def checkCount(expected_count)
actual_count = Li_std_auto_ptr::Klass.getTotal_count()
if (actual_count != expected_count)
raise RuntimeError, "Counts incorrect, expected:" + expected_count + " actual:" + actual_count
end
end
# auto_ptr as input
kin = Li_std_auto_ptr::Klass.new("KlassInput")
checkCount(1)
s = Li_std_auto_ptr.takeKlassAutoPtr(kin)
checkCount(0)
if (s != "KlassInput")
raise RuntimeError, "Incorrect string: " + s
end
exception_thrown = false
begin
Li_std_auto_ptr.is_nullptr(kin)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
kin = nil
checkCount(0)
kin = Li_std_auto_ptr::Klass.new("KlassInput")
checkCount(1)
s = Li_std_auto_ptr.takeKlassAutoPtr(kin)
checkCount(0)
if (s != "KlassInput")
raise RuntimeError, "Incorrect string: " + s
end
exception_thrown = false
begin
Li_std_auto_ptr.is_nullptr(kin)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
exception_thrown = false
begin
Li_std_auto_ptr.takeKlassAutoPtr(kin)
rescue RuntimeError => e
# puts e.message
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "double usage of takeKlassAutoPtr should have been an error"
end
kin = nil
checkCount(0)
kin = Li_std_auto_ptr::Klass.new("KlassInput")
exception_thrown = false
begin
notowned = Li_std_auto_ptr::get_not_owned_ptr(kin)
Li_std_auto_ptr::takeKlassAutoPtr(notowned)
rescue RuntimeError
if (!e.to_s.include? "cannot release ownership as memory is not owned")
raise RuntimeError, "incorrect exception message"
end
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "Should have thrown 'Cannot release ownership as memory is not owned' error"
end
Li_std_auto_ptr.takeKlassAutoPtr(kin) # Ensure object is deleted (can't rely on GC)
checkCount(0)
kini = Li_std_auto_ptr::KlassInheritance.new("KlassInheritanceInput")
checkCount(1)
s = Li_std_auto_ptr.takeKlassAutoPtr(kini)
checkCount(0)
if (s != "KlassInheritanceInput")
raise RuntimeError, "Incorrect string: " + s
end
exception_thrown = false
begin
Li_std_auto_ptr.is_nullptr(kini)
rescue ObjectPreviouslyDeleted
exception_thrown = true
end
if (!exception_thrown)
raise RuntimeError, "is_nullptr failed to throw"
end
kini = nil
checkCount(0)
# auto_ptr as output
k1 = Li_std_auto_ptr::makeKlassAutoPtr("first")
k2 = Li_std_auto_ptr::makeKlassAutoPtr("second")
swig_assert_equal_simple(2, Li_std_auto_ptr::Klass::getTotal_count())

View File

@ -913,6 +913,19 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
}
CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) {
if (obj != null) {
if (!obj.swigCMemOwn)
throw new global::System.ApplicationException("Cannot release ownership as memory is not owned");
global::System.Runtime.InteropServices.HandleRef ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.Dispose();
return ptr;
} else {
return new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
}
%}
// Derived proxy classes
@ -926,6 +939,19 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
}
CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) {
if (obj != null) {
if (!obj.swigCMemOwn)
throw new global::System.ApplicationException("Cannot release ownership as memory is not owned");
global::System.Runtime.InteropServices.HandleRef ptr = obj.swigCPtr;
obj.swigCMemOwn = false;
obj.Dispose();
return ptr;
} else {
return new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero);
}
}
%}
%enddef
@ -945,6 +971,10 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef getCPtr($csclassname obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
}
CPTR_VISIBILITY static global::System.Runtime.InteropServices.HandleRef swigRelease($csclassname obj) {
return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr;
}
%}
%typemap(csbody) TYPE (CLASS::*) %{

View File

@ -1,27 +1,36 @@
/* -----------------------------------------------------------------------------
* std_auto_ptr.i
*
* The typemaps here allow handling functions returning std::auto_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::auto_ptr.
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
* class when returning a std::auto_ptr from a function.
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %auto_ptr(TYPE)
%typemap (ctype) std::auto_ptr< TYPE > "void *"
%typemap (imtype, out="System.IntPtr") std::auto_ptr< TYPE > "HandleRef"
%typemap (imtype, out="System.IntPtr") std::auto_ptr< TYPE > "global::System.Runtime.InteropServices.HandleRef"
%typemap (cstype) std::auto_ptr< TYPE > "$typemap(cstype, TYPE)"
%typemap(in) std::auto_ptr< TYPE >
%{ $1.reset((TYPE *)$input); %}
%typemap(csin) std::auto_ptr< TYPE > "$typemap(cstype, TYPE).swigRelease($csinput)"
%typemap (out) std::auto_ptr< TYPE > %{
$result = (void *)$1.release();
$result = (void *)$1.release();
%}
%typemap(csout, excode=SWIGEXCODE) std::auto_ptr< TYPE > {
System.IntPtr cPtr = $imcall;
$typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode
return ret;
}
System.IntPtr cPtr = $imcall;
$typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode
return ret;
}
%template() std::auto_ptr< TYPE >;
%enddef
namespace std {
template <class T> class auto_ptr {};
}
template <class T> class auto_ptr {};
}

View File

@ -1,27 +1,36 @@
/* -----------------------------------------------------------------------------
* std_unique_ptr.i
*
* The typemaps here allow handling functions returning std::unique_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::unique_ptr.
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
* class when returning a std::unique_ptr from a function.
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %unique_ptr(TYPE)
%typemap (ctype) std::unique_ptr< TYPE > "void *"
%typemap (imtype, out="System.IntPtr") std::unique_ptr< TYPE > "HandleRef"
%typemap (imtype, out="System.IntPtr") std::unique_ptr< TYPE > "global::System.Runtime.InteropServices.HandleRef"
%typemap (cstype) std::unique_ptr< TYPE > "$typemap(cstype, TYPE)"
%typemap(in) std::unique_ptr< TYPE >
%{ $1.reset((TYPE *)$input); %}
%typemap(csin) std::unique_ptr< TYPE > "$typemap(cstype, TYPE).swigRelease($csinput)"
%typemap (out) std::unique_ptr< TYPE > %{
$result = (void *)$1.release();
$result = (void *)$1.release();
%}
%typemap(csout, excode=SWIGEXCODE) std::unique_ptr< TYPE > {
System.IntPtr cPtr = $imcall;
$typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode
return ret;
}
System.IntPtr cPtr = $imcall;
$typemap(cstype, TYPE) ret = (cPtr == System.IntPtr.Zero) ? null : new $typemap(cstype, TYPE)(cPtr, true);$excode
return ret;
}
%template() std::unique_ptr< TYPE >;
%enddef
namespace std {
template <class T> class unique_ptr {};
}
template <class T> class unique_ptr {};
}

View File

@ -700,6 +700,7 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); }
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "$1_type reference is null");
return $null;
} %}
%typemap(freearg) SWIGTYPE && %{ delete $1; %};
%typemap(out) SWIGTYPE *
%{ *($&1_ltype)&$result = $1; %}
%typemap(out, fragment="SWIG_PackData", noblock=1) SWIGTYPE (CLASS::*) {
@ -1101,7 +1102,8 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); }
jobjectArray
"$javainput"
%typemap(javain) SWIGTYPE "$&javaclassname.getCPtr($javainput)"
%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE &&, SWIGTYPE [] "$javaclassname.getCPtr($javainput)"
%typemap(javain) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "$javaclassname.getCPtr($javainput)"
%typemap(javain) SWIGTYPE && "$javaclassname.swigRelease($javainput)"
%typemap(javain) SWIGTYPE (CLASS::*) "$javaclassname.getCMemberPtr($javainput)"
/* The javaout typemap is used for converting function return types from the return type
@ -1216,6 +1218,18 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); }
CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
CPTR_VISIBILITY 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;
}
%}
// Derived proxy classes
@ -1230,6 +1244,18 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); }
CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
CPTR_VISIBILITY 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;
}
%}
%enddef
@ -1249,6 +1275,10 @@ Swig::LocalRefGuard $1_refguard(jenv, $input); }
CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
CPTR_VISIBILITY static long swigRelease($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
%}
%typemap(javabody) TYPE (CLASS::*) %{

View File

@ -1,29 +1,39 @@
/* -----------------------------------------------------------------------------
* std_auto_ptr.i
*
* The typemaps here allow handling functions returning std::auto_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::auto_ptr.
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
* class when returning a std::auto_ptr from a function.
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %auto_ptr(TYPE)
%typemap (jni) std::auto_ptr< TYPE > "jlong"
%typemap (jtype) std::auto_ptr< TYPE > "long"
%typemap (jstype) std::auto_ptr< TYPE > "$typemap(jstype, TYPE)"
%typemap(in) std::auto_ptr< TYPE > (TYPE *auto_temp)
%{ auto_temp = *(TYPE **)&$input;
$1.reset(auto_temp); %}
%typemap(javain) std::auto_ptr< TYPE > "$typemap(jstype, TYPE).swigRelease($javainput)"
%typemap (out) std::auto_ptr< TYPE > %{
jlong lpp = 0;
*(TYPE **) &lpp = $1.release();
$result = lpp;
jlong lpp = 0;
*(TYPE **) &lpp = $1.release();
$result = lpp;
%}
%typemap(javaout) std::auto_ptr< TYPE > {
long cPtr = $jnicall;
return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
}
long cPtr = $jnicall;
return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
}
%template() std::auto_ptr< TYPE >;
%enddef
namespace std {
template <class T> class auto_ptr {};
}
template <class T> class auto_ptr {};
}

View File

@ -1,29 +1,39 @@
/* -----------------------------------------------------------------------------
* std_unique_ptr.i
*
* The typemaps here allow handling functions returning std::unique_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::unique_ptr.
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
* class when returning a std::unique_ptr from a function.
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%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;
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);
}
long cPtr = $jnicall;
return (cPtr == 0) ? null : new $typemap(jstype, TYPE)(cPtr, true);
}
%template() std::unique_ptr< TYPE >;
%enddef
namespace std {
template <class T> class unique_ptr {};
}
template <class T> class unique_ptr {};
}

View File

@ -210,6 +210,7 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_
swig_cast_info *tc;
void *voidptr = (void *)0;
SV *tsv = 0;
int check_owned_pointer_release = (flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE;
if (own)
*own = 0;
@ -286,13 +287,14 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_
/*
* DISOWN implementation: we need a perl guru to check this one.
*/
if (tsv && (flags & SWIG_POINTER_DISOWN)) {
if (tsv && ((flags & SWIG_POINTER_DISOWN) || check_owned_pointer_release)) {
/*
* almost copy paste code from below SWIG_POINTER_OWN setting
*/
SV *obj = sv;
HV *stash = SvSTASH(SvRV(obj));
GV *gv = *(GV**)hv_fetch(stash, "OWNER", 5, TRUE);
int owned = 0;
if (isGV(gv)) {
HV *hv = GvHVn(gv);
/*
@ -300,10 +302,21 @@ SWIG_Perl_ConvertPtrAndOwn(SWIG_MAYBE_PERL_OBJECT SV *sv, void **ptr, swig_type_
* Hence, to remove ownership, we delete the entry.
*/
if (hv_exists_ent(hv, obj, 0)) {
hv_delete_ent(hv, obj, 0, 0);
owned = 1;
if (flags & SWIG_POINTER_DISOWN) {
hv_delete_ent(hv, obj, 0, 0);
}
}
}
if (check_owned_pointer_release && !owned) {
return SWIG_ERROR_RELEASE_NOT_OWNED;
}
}
if (tsv && (flags & SWIG_POINTER_CLEAR)) {
SvIV_set(tsv, 0);
}
return SWIG_OK;
}

View File

@ -1,19 +1,33 @@
/* -----------------------------------------------------------------------------
* std_auto_ptr.i
*
* The typemaps here allow handling functions returning std::auto_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::auto_ptr.
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
* class when returning a std::auto_ptr from a function.
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %auto_ptr(TYPE)
%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
} else {
%argument_fail(res, "TYPE *", $symname, $argnum);
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::auto_ptr< TYPE > %{
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%}
%template() std::auto_ptr< TYPE >;
%enddef
namespace std {
template <class T> class auto_ptr {};
template <class T> class auto_ptr {};
}

View File

@ -1,19 +1,33 @@
/* -----------------------------------------------------------------------------
* std_unique_ptr.i
*
* The typemaps here allow handling functions returning std::unique_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::unique_ptr.
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
* class when returning a std::unique_ptr from a function.
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %unique_ptr(TYPE)
%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
} else {
%argument_fail(res, "TYPE *", $symname, $argnum);
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::unique_ptr< TYPE > %{
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%}
%template() std::unique_ptr< TYPE >;
%enddef
namespace std {
template <class T> class unique_ptr {};
template <class T> class unique_ptr {};
}

View File

@ -1357,12 +1357,19 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
}
}
if (sobj) {
if (own)
*own = *own | sobj->own;
if (flags & SWIG_POINTER_DISOWN) {
sobj->own = 0;
if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !sobj->own) {
res = SWIG_ERROR_RELEASE_NOT_OWNED;
} else {
if (own)
*own = *own | sobj->own;
if (flags & SWIG_POINTER_DISOWN) {
sobj->own = 0;
}
if (flags & SWIG_POINTER_CLEAR) {
sobj->ptr = 0;
}
res = SWIG_OK;
}
res = SWIG_OK;
} else {
if (implicit_conv) {
SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;

View File

@ -1,19 +1,33 @@
/* -----------------------------------------------------------------------------
* std_auto_ptr.i
*
* The typemaps here allow handling functions returning std::auto_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::auto_ptr.
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
* class when returning a std::auto_ptr from a function.
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %auto_ptr(TYPE)
%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
} else {
%argument_fail(res, "TYPE *", $symname, $argnum);
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::auto_ptr< TYPE > %{
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%}
%template() std::auto_ptr< TYPE >;
%enddef
namespace std {
template <class T> class auto_ptr {};
}
template <class T> class auto_ptr {};
}

View File

@ -1,19 +1,33 @@
/* -----------------------------------------------------------------------------
* std_unique_ptr.i
*
* The typemaps here allow handling functions returning std::unique_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::unique_ptr.
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
* class when returning a std::unique_ptr from a function.
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %unique_ptr(TYPE)
%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
} else {
%argument_fail(res, "TYPE *", $symname, $argnum);
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::unique_ptr< TYPE > %{
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%}
%template() std::unique_ptr< TYPE >;
%enddef
namespace std {
template <class T> class unique_ptr {};
}
template <class T> class unique_ptr {};
}

View File

@ -281,6 +281,11 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags,
own->own = 0;
}
if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE)) {
if (!RDATA(obj)->dfree)
return SWIG_ERROR_RELEASE_NOT_OWNED;
}
/* Check to see if the input object is giving up ownership
of the underlying C struct or C++ object. If so then we
need to reset the destructor since the Ruby object no
@ -292,7 +297,7 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags,
swig_class *sklass = (swig_class *) ty->clientdata;
track = sklass->trackObjects;
}
if (track) {
/* We are tracking objects for this class. Thus we change the destructor
* to SWIG_RubyRemoveTracking. This allows us to
@ -306,6 +311,10 @@ SWIG_Ruby_ConvertPtrAndOwn(VALUE obj, void **ptr, swig_type_info *ty, int flags,
}
}
if (flags & SWIG_POINTER_CLEAR) {
DATA_PTR(obj) = 0;
}
/* Do type-checking if type info was provided */
if (ty) {
if (ty->clientdata) {

View File

@ -1,19 +1,33 @@
/* -----------------------------------------------------------------------------
* std_auto_ptr.i
*
* The typemaps here allow handling functions returning std::auto_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::auto_ptr.
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
* class when returning a std::auto_ptr from a function.
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %auto_ptr(TYPE)
%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
} else {
%argument_fail(res, "TYPE *", $symname, $argnum);
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::auto_ptr< TYPE > %{
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%}
%template() std::auto_ptr< TYPE >;
%enddef
namespace std {
template <class T> class auto_ptr {};
template <class T> class auto_ptr {};
}

View File

@ -1,19 +1,33 @@
/* -----------------------------------------------------------------------------
* std_unique_ptr.i
*
* The typemaps here allow handling functions returning std::unique_ptr<>,
* which is the most common use of this type. If you have functions taking it
* as parameter, these typemaps can't be used for them and you need to do
* something else (e.g. use shared_ptr<> which SWIG supports fully).
* SWIG library file for handling std::unique_ptr.
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
* class when returning a std::unique_ptr from a function.
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %unique_ptr(TYPE)
%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
} else {
%argument_fail(res, "TYPE *", $symname, $argnum);
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::unique_ptr< TYPE > %{
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%}
%template() std::unique_ptr< TYPE >;
%enddef
namespace std {
template <class T> class unique_ptr {};
template <class T> class unique_ptr {};
}

View File

@ -1,4 +1,4 @@
/* Errors in SWIG */
/* SWIG Errors applicable to all language modules, values are reserved from -1 to -99 */
#define SWIG_UnknownError -1
#define SWIG_IOError -2
#define SWIG_RuntimeError -3
@ -13,4 +13,3 @@
#define SWIG_MemoryError -12
#define SWIG_NullReferenceError -13

View File

@ -44,6 +44,8 @@
#define SWIG_POINTER_DISOWN 0x1
#define SWIG_CAST_NEW_MEMORY 0x2
#define SWIG_POINTER_NO_NULL 0x4
#define SWIG_POINTER_CLEAR 0x8
#define SWIG_POINTER_RELEASE (SWIG_POINTER_CLEAR | SWIG_POINTER_DISOWN)
/* Flags for new pointer objects */
#define SWIG_POINTER_OWN 0x1
@ -129,7 +131,13 @@
*/
#define SWIG_OK (0)
/* Runtime errors are < 0 */
#define SWIG_ERROR (-1)
/* Errors in range -1 to -99 are in swigerrors.swg (errors for all languages including those not using the runtime) */
/* Errors in range -100 to -199 are language specific errors defined in *errors.swg */
/* Errors < -200 are generic runtime specific errors */
#define SWIG_ERROR_RELEASE_NOT_OWNED (-200)
#define SWIG_IsOK(r) (r >= 0)
#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError)
@ -144,7 +152,7 @@
#define SWIG_OLDOBJ (SWIG_OK)
#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK)
#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK)
/* Check, add and del mask methods */
/* Check, add and del object mask methods */
#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))

View File

@ -19,6 +19,7 @@
#endif
#define %varnullref_fmt(_type,_name) %nullref_fmt() %varfail_fmt(_type, _name)
#define %outnullref_fmt(_type) %nullref_fmt() %outfail_fmt(_type)
#define %releasenotownedfail_fmt(_type,_name,_argn) "in method '" `_name` "', cannot release ownership as memory is not owned for argument " `_argn`" of type '" `_type`"'"
/* setting an error */
#define %error(code,msg...) SWIG_Error(code, msg)

View File

@ -140,6 +140,7 @@
#define %argument_nullref(type, name, argn) SWIG_exception_fail(SWIG_ValueError, %argnullref_fmt(type, name, argn))
#define %variable_fail(code, type, name) SWIG_exception_fail(%default_code(code), %varfail_fmt(type, name))
#define %variable_nullref(type, name) SWIG_exception_fail(SWIG_ValueError, %varnullref_fmt(type, name))
#define %releasenotowned_fail(code, type, name, argn) SWIG_exception_fail(%default_code(code), %releasenotownedfail_fmt(type, name, argn))
#if defined(SWIG_DIRECTOR_TYPEMAPS)
#define %dirout_fail(code, type) SWIG_DirOutFail(%default_code(code), %outfail_fmt(type))