diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index c319f4bb8..893c25cc0 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -896,6 +896,18 @@ public: return type_caster_base::cast_holder(ptr, &src); } + // This function will succeed even if the `responsible_parent` does not own the + // wrapped C++ object directly. + // It is the responsibility of the caller to ensure that the `responsible_parent` + // has a `keep_alive` relationship with the owner of the wrapped C++ object, or + // that the wrapped C++ object lives for the duration of the process. + static std::shared_ptr shared_ptr_with_responsible_parent(handle responsible_parent) { + copyable_holder_caster loader; + loader.load(responsible_parent, /*convert=*/false); + assert(loader.typeinfo->default_holder); + return loader.sh_load_helper.loaded_as_shared_ptr(loader.value, responsible_parent); + } + protected: friend class type_caster_generic; void check_holder_compat() {} diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index e94979492..49f278561 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1647,7 +1647,8 @@ struct property_cpp_function< if (tinfo->default_holder) { return cpp_function( [pm](handle c_hdl) -> std::shared_ptr { - auto c_sp = cast>(c_hdl); + std::shared_ptr c_sp = detail::type_caster< + std::shared_ptr>::shared_ptr_with_responsible_parent(c_hdl); D ptr = (*c_sp).*pm; return std::shared_ptr(c_sp, ptr); }, @@ -1694,7 +1695,8 @@ struct property_cpp_function< if (tinfo->default_holder) { return cpp_function( [pm](handle c_hdl) -> std::shared_ptr::type> { - auto c_sp = cast>(c_hdl); + std::shared_ptr c_sp = detail::type_caster< + std::shared_ptr>::shared_ptr_with_responsible_parent(c_hdl); return std::shared_ptr::type>(c_sp, &(c_sp.get()->*pm)); }, @@ -1709,7 +1711,8 @@ struct property_cpp_function< if (tinfo->default_holder) { return cpp_function( [pm](handle c_hdl) -> std::shared_ptr { - auto c_sp = cast>(c_hdl); + std::shared_ptr c_sp = detail::type_caster< + std::shared_ptr>::shared_ptr_with_responsible_parent(c_hdl); return std::shared_ptr(c_sp, &(c_sp.get()->*pm)); }, is_method(hdl)); @@ -1757,7 +1760,8 @@ struct property_cpp_function< if (tinfo->default_holder) { return cpp_function( [pm](handle c_hdl) -> D { - auto c_sp = cast>(c_hdl); + std::shared_ptr c_sp = detail::type_caster< + std::shared_ptr>::shared_ptr_with_responsible_parent(c_hdl); return D{std::move(c_sp.get()->*pm)}; }, is_method(hdl));