There are quite a few possibilities in SWIG for using useful things, using the general support for smart pointers in SWIG, despite the lack of support in C ++ 11 notes noted.
In short, if there is an operator-> , then SWIG combined the members of the pointer into a pointer to allow them to be used for a long time within the target language.
I put together a complete example of how this might work for you using the hader test.hh example file below:
#include <memory> #include <iostream> struct Foobar { void baz() { std::cout << "This works\n"; } int wibble; }; std::unique_ptr<Foobar> make_example() { return std::unique_ptr<Foobar>(new Foobar); } void dump_example(const std::unique_ptr<Foobar>& in) { std::cout << in->wibble << "\n"; in->baz(); }
To use unique_ptr intelligently inside Python, I had to write the following SWIG file, std_unique_ptr.i:
namespace std { %feature("novaluewrapper") unique_ptr; template <typename Type> struct unique_ptr { typedef Type* pointer; explicit unique_ptr( pointer Ptr ); unique_ptr (unique_ptr&& Right); template<class Type2, Class Del2> unique_ptr( unique_ptr<Type2, Del2>&& Right ); unique_ptr( const unique_ptr& Right) = delete; pointer operator-> () const; pointer release (); void reset (pointer __p=pointer()); void swap (unique_ptr &__u); pointer get () const; operator bool () const; ~unique_ptr(); }; } %define wrap_unique_ptr(Name, Type) %template(Name) std::unique_ptr<Type>; %newobject std::unique_ptr<Type>::release; %typemap(out) std::unique_ptr<Type> %{ $result = SWIG_NewPointerObj(new $1_ltype(std::move($1)), $&1_descriptor, SWIG_POINTER_OWN); %} %enddef
which includes a sufficient number of subsets of std::unique_ptr . (You can add or remove constructors depending on what kind of semantics you want to use in Python, I did not pay attention to custom removers here).
He also adds the wrap_unique_ptr macro, which installs support. A sample map simply forces the generated SWIG code to use the move constructor instead of the copy constructor when returning by value.
We can use it as follows:
%module test %{ #include "test.hh" %} %include "std_unique_ptr.i" wrap_unique_ptr(FooUniquePtr, Foobar); %include "test.hh"
I built it with
swig3.0 -py3 -c++ -python -Wall test.i g++ -Wall -Wextra -Wno-missing-field-initializers test_wrap.cxx -std=c++11 -I/usr/include/python3.4/ -lpython3.4m -shared -o _test.so
This allows us to use the following Python:
from test import * a = make_example() print(a) a.wibble = 1234567 a.baz() dump_example(a) a.baz() print(bool(a)) print(bool(FooUniquePtr(None))) b=a.release() print(b)
Note that despite unique_ptr<Foobar> , we can still say a.baz() and a.wibble . The release() method also returns a useful "raw" pointer, which is now owned by Python (since otherwise it would not have an owner). get() returns a borrowed pointer inside Python, as you expected.
Depending on how you plan to use pointers, this is probably a good start for your own types and cleanup than %extend and release() wherever you have unique_ptrs.
Compared to %shared_ptr this does not change in typemaps and does not change the constructors in the same way as shared_ptr support. It is your responsibility to choose when raw pointers become unique_ptrs inside Python.
I wrote a similar answer using std::weak_ptr with SWIG some time ago.