diff --git a/docs/advanced.rst b/docs/advanced.rst index 74611bd20..43366d9ca 100644 --- a/docs/advanced.rst +++ b/docs/advanced.rst @@ -527,9 +527,40 @@ Python side: py::implicitly_convertible(); +Unique pointers +=============== + +Given a class ``Example`` with Python bindings, it's possible to return +instances wrapped in C++11 unique pointers, like so + +.. code-block:: cpp + + std::unique_ptr create_example() { return std::unique_ptr(new Example()); } + +.. code-block:: cpp + + m.def("create_example", &create_example); + +In other words, there is nothing special that needs to be done. While returning +unique pointers in this way is allowed, it is *illegal* to use them as function +arguments. For instance, the following function signature cannot be processed +by pybind11. + +.. code-block:: cpp + + void do_something_with_example(std::unique_ptr ex) { ... } + +The above signature would imply that Python needs to give up ownership of an +object that is passed to this function, which is generally not possible (for +instance, the object might be referenced elsewhere). + Smart pointers ============== +This section explains how to pass values that are wrapped in "smart" pointer +types with internal reference counting. For simpler C++11 unique pointers, +please refer to the previous section. + The binding generator for classes (:class:`class_`) takes an optional second template type, which denotes a special *holder* type that is used to manage references to the object. When wrapping a type named ``Type``, the default diff --git a/example/example14.cpp b/example/example14.cpp index 6a33ba775..abae02140 100644 --- a/example/example14.cpp +++ b/example/example14.cpp @@ -31,4 +31,10 @@ void init_ex14(py::module &m) { m.def("print_void_ptr", [](void *ptr) { std::cout << "Got void ptr : " << (uint64_t) ptr << std::endl; }); m.def("return_null_str", []() { return (char *) nullptr; }); m.def("print_null_str", [](char *ptr) { std::cout << "Got null str : " << (uint64_t) ptr << std::endl; }); + + m.def("return_unique_ptr", []() -> std::unique_ptr { + StringList *result = new StringList(); + result->push_back("some value"); + return std::unique_ptr(result); + }); } diff --git a/example/example14.py b/example/example14.py index 08f5d46a5..82d14de84 100644 --- a/example/example14.py +++ b/example/example14.py @@ -6,6 +6,7 @@ sys.path.append('.') from example import StringList, print_opaque_list from example import return_void_ptr, print_void_ptr from example import return_null_str, print_null_str +from example import return_unique_ptr l = StringList() l.push_back("Element 1") @@ -19,3 +20,5 @@ print_void_ptr(return_void_ptr()) print(return_null_str()) print_null_str(return_null_str()) + +print(return_unique_ptr()) diff --git a/example/example14.ref b/example/example14.ref index 7554a5ebd..b4768efe9 100644 --- a/example/example14.ref +++ b/example/example14.ref @@ -7,3 +7,4 @@ Opaque list: Got void ptr : 1234 None Got null str : 0 +[u'some value'] diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 55030f6d7..d0608f36a 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -405,6 +405,17 @@ protected: bool success = false; }; +template class type_caster> { +public: + static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { + handle result = type_caster::cast(src.get(), policy, parent); + if (result) + src.release(); + return result; + } + static PYBIND11_DESCR name() { return type_caster::name(); } +}; + template <> class type_caster { public: bool load(handle src, bool) {