mirror of
https://github.com/pybind/pybind11.git
synced 2026-03-14 20:27:47 +00:00
Support take_ownership for custom type casters given a pointer
This changes the pointer `cast()` in `PYBIND11_TYPE_CASTER` to recognize
the `take_ownership` policy: if casting a pointer with take-ownership,
the `cast()` now recalls `cast()` with a dereferenced rvalue (rather
than the previous code, which was always calling it with a const lvalue
reference), and deletes the pointer after the chained `cast()` is
complete.
This makes code like:
m.def("f", []() { return new std::vector<int>(100, 1); },
py::return_value_policy::take_ownership);
do the expected thing by taking over ownership of the returned pointer
(which is deleted once the chained cast completes).
This commit is contained in:
@@ -154,7 +154,28 @@ public:
|
||||
}
|
||||
|
||||
static handle cast(const ArgAlwaysConverts &, return_value_policy, handle) {
|
||||
return py::none();
|
||||
return py::none().release();
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
// test_custom_caster_destruction
|
||||
class DestructionTester {
|
||||
public:
|
||||
DestructionTester() { print_default_created(this); }
|
||||
~DestructionTester() { print_destroyed(this); }
|
||||
DestructionTester(const DestructionTester &) { print_copy_created(this); }
|
||||
DestructionTester(DestructionTester &&) { print_move_created(this); }
|
||||
DestructionTester &operator=(const DestructionTester &) { print_copy_assigned(this); return *this; }
|
||||
DestructionTester &operator=(DestructionTester &&) { print_move_assigned(this); return *this; }
|
||||
};
|
||||
namespace pybind11 { namespace detail {
|
||||
template <> struct type_caster<DestructionTester> {
|
||||
PYBIND11_TYPE_CASTER(DestructionTester, _("DestructionTester"));
|
||||
bool load(handle, bool) { return true; }
|
||||
|
||||
static handle cast(const DestructionTester &, return_value_policy, handle) {
|
||||
return py::bool_(true).release();
|
||||
}
|
||||
};
|
||||
}}
|
||||
@@ -399,4 +420,16 @@ test_initializer methods_and_attributes([](py::module &m) {
|
||||
|
||||
using Adapted = decltype(py::method_adaptor<RegisteredDerived>(&RegisteredDerived::do_nothing));
|
||||
static_assert(std::is_same<Adapted, void (RegisteredDerived::*)() const>::value, "");
|
||||
|
||||
// test_custom_caster_destruction
|
||||
// Test that `take_ownership` works on types with a custom type caster when given a pointer
|
||||
|
||||
// default policy: don't take ownership:
|
||||
m.def("custom_caster_no_destroy", []() { static auto *dt = new DestructionTester(); return dt; });
|
||||
|
||||
m.def("custom_caster_destroy", []() { return new DestructionTester(); },
|
||||
py::return_value_policy::take_ownership); // Takes ownership: destroy when finished
|
||||
m.def("custom_caster_destroy_const", []() -> const DestructionTester * { return new DestructionTester(); },
|
||||
py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
|
||||
m.def("destruction_tester_cstats", &ConstructorStats::get<DestructionTester>, py::return_value_policy::reference);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user