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:
Jason Rhinelander
2017-07-07 17:26:14 -04:00
parent 67a0cc4eed
commit 60526d4636
3 changed files with 66 additions and 2 deletions

View File

@@ -477,3 +477,30 @@ def test_unregistered_base_implementations():
assert a.rw_value_prop == 49
a.increase_value()
assert a.ro_value_prop == 1.75
def test_custom_caster_destruction():
"""
Tests that returning a pointer to a type that gets converted with a custom type caster gets
destroyed when the function has py::return_value_policy::take_ownership policy applied.
"""
import pybind11_tests as m
cstats = m.destruction_tester_cstats()
# This one *doesn't* have take_ownership: the pointer should be used but not destroyed:
z = m.custom_caster_no_destroy()
assert cstats.alive() == 1 and cstats.default_constructions == 1
assert z
# take_ownership applied: this constructs a new object, casts it, then destroys it:
z = m.custom_caster_destroy()
assert z
assert cstats.default_constructions == 2
# Same, but with a const pointer return (which should *not* inhibit destruction):
z = m.custom_caster_destroy_const()
assert z
assert cstats.default_constructions == 3
# Make sure we still only have the original object (from ..._no_destroy()) alive:
assert cstats.alive() == 1