From db5e37a1d7b80304a9c9875b01cfd585070a288a Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Mon, 18 Jul 2022 08:32:26 +0100 Subject: [PATCH] Add support for std::auto_ptr inputs Ported from std::unique, behaviour is identical with regard to memory ownership/handling --- .../csharp/li_std_auto_ptr_runme.cs | 63 +++++++++++++ .../java/li_std_auto_ptr_runme.java | 70 ++++++++++++++ Examples/test-suite/li_std_auto_ptr.i | 30 +++++- .../test-suite/perl5/li_std_auto_ptr_runme.pl | 60 +++++++++++- .../python/li_std_auto_ptr_runme.py | 65 +++++++++++++ .../test-suite/ruby/li_std_auto_ptr_runme.rb | 91 +++++++++++++++++++ Lib/csharp/std_auto_ptr.i | 31 ++++--- Lib/java/std_auto_ptr.i | 34 ++++--- Lib/perl5/std_auto_ptr.i | 26 ++++-- Lib/python/std_auto_ptr.i | 28 ++++-- Lib/ruby/std_auto_ptr.i | 26 ++++-- 11 files changed, 477 insertions(+), 47 deletions(-) diff --git a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs index 863b86701..b804e7ead 100644 --- a/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs +++ b/Examples/test-suite/csharp/li_std_auto_ptr_runme.cs @@ -9,8 +9,71 @@ 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) { + 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) { + 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"); diff --git a/Examples/test-suite/java/li_std_auto_ptr_runme.java b/Examples/test-suite/java/li_std_auto_ptr_runme.java index 50ed113a4..40957e974 100644 --- a/Examples/test-suite/java/li_std_auto_ptr_runme.java +++ b/Examples/test-suite/java/li_std_auto_ptr_runme.java @@ -20,8 +20,78 @@ 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) { + 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) { + 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"); diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index edfe2ccf5..02c8235f2 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -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 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; - %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 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 makeKlassAutoPtr(const char* label) { return std::auto_ptr(new Klass(label)); } diff --git a/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl index 52cb23ac5..8a33f4562 100644 --- a/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl +++ b/Examples/test-suite/perl5/li_std_auto_ptr_runme.pl @@ -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"); diff --git a/Examples/test-suite/python/li_std_auto_ptr_runme.py b/Examples/test-suite/python/li_std_auto_ptr_runme.py index d62224ff6..3f1d392ea 100644 --- a/Examples/test-suite/python/li_std_auto_ptr_runme.py +++ b/Examples/test-suite/python/li_std_auto_ptr_runme.py @@ -1,5 +1,70 @@ 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: + 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: diff --git a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb index cec48a58c..14e0bd9d4 100644 --- a/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb +++ b/Examples/test-suite/ruby/li_std_auto_ptr_runme.rb @@ -11,6 +11,97 @@ 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 + 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()) diff --git a/Lib/csharp/std_auto_ptr.i b/Lib/csharp/std_auto_ptr.i index b1ec3d569..78d7eaf4c 100644 --- a/Lib/csharp/std_auto_ptr.i +++ b/Lib/csharp/std_auto_ptr.i @@ -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 > "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 auto_ptr {}; -} + template class auto_ptr {}; +} diff --git a/Lib/java/std_auto_ptr.i b/Lib/java/std_auto_ptr.i index 0eb5fe155..6d65f0451 100644 --- a/Lib/java/std_auto_ptr.i +++ b/Lib/java/std_auto_ptr.i @@ -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 auto_ptr {}; -} + template class auto_ptr {}; +} diff --git a/Lib/perl5/std_auto_ptr.i b/Lib/perl5/std_auto_ptr.i index ecaea2b0f..d062886e4 100644 --- a/Lib/perl5/std_auto_ptr.i +++ b/Lib/perl5/std_auto_ptr.i @@ -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 auto_ptr {}; + template class auto_ptr {}; } diff --git a/Lib/python/std_auto_ptr.i b/Lib/python/std_auto_ptr.i index fb044f851..d062886e4 100644 --- a/Lib/python/std_auto_ptr.i +++ b/Lib/python/std_auto_ptr.i @@ -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 auto_ptr {}; -} + template class auto_ptr {}; +} diff --git a/Lib/ruby/std_auto_ptr.i b/Lib/ruby/std_auto_ptr.i index ecaea2b0f..d062886e4 100644 --- a/Lib/ruby/std_auto_ptr.i +++ b/Lib/ruby/std_auto_ptr.i @@ -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 auto_ptr {}; + template class auto_ptr {}; }