returning unique pointers is now allowed

This commit is contained in:
Wenzel Jakob 2016-04-06 17:38:18 +02:00
parent a3ee1a4591
commit 9f0dfce84b
5 changed files with 52 additions and 0 deletions

View File

@ -527,9 +527,40 @@ Python side:
py::implicitly_convertible<A, B>(); py::implicitly_convertible<A, B>();
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<Example> create_example() { return std::unique_ptr<Example>(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<Example> 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 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 The binding generator for classes (:class:`class_`) takes an optional second
template type, which denotes a special *holder* type that is used to manage 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 references to the object. When wrapping a type named ``Type``, the default

View File

@ -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("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("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("print_null_str", [](char *ptr) { std::cout << "Got null str : " << (uint64_t) ptr << std::endl; });
m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
StringList *result = new StringList();
result->push_back("some value");
return std::unique_ptr<StringList>(result);
});
} }

View File

@ -6,6 +6,7 @@ sys.path.append('.')
from example import StringList, print_opaque_list from example import StringList, print_opaque_list
from example import return_void_ptr, print_void_ptr from example import return_void_ptr, print_void_ptr
from example import return_null_str, print_null_str from example import return_null_str, print_null_str
from example import return_unique_ptr
l = StringList() l = StringList()
l.push_back("Element 1") l.push_back("Element 1")
@ -19,3 +20,5 @@ print_void_ptr(return_void_ptr())
print(return_null_str()) print(return_null_str())
print_null_str(return_null_str()) print_null_str(return_null_str())
print(return_unique_ptr())

View File

@ -7,3 +7,4 @@ Opaque list:
Got void ptr : 1234 Got void ptr : 1234
None None
Got null str : 0 Got null str : 0
[u'some value']

View File

@ -405,6 +405,17 @@ protected:
bool success = false; bool success = false;
}; };
template <typename type> class type_caster<std::unique_ptr<type>> {
public:
static handle cast(std::unique_ptr<type> &&src, return_value_policy policy, handle parent) {
handle result = type_caster<type>::cast(src.get(), policy, parent);
if (result)
src.release();
return result;
}
static PYBIND11_DESCR name() { return type_caster<type>::name(); }
};
template <> class type_caster<std::wstring> { template <> class type_caster<std::wstring> {
public: public:
bool load(handle src, bool) { bool load(handle src, bool) {