mirror of
https://github.com/pybind/pybind11.git
synced 2025-03-03 21:13:20 +00:00
Calling deregister_instance after disowning via unique_ptr.
This commit is contained in:
parent
b85cc69714
commit
b41a0db1b1
@ -54,17 +54,35 @@ using namespace pybind11_tests::classh_wip;
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct smart_holder_type_caster_load {
|
struct smart_holder_type_caster_load {
|
||||||
|
using holder_type = pybindit::memory::smart_holder;
|
||||||
|
|
||||||
bool load(handle src, bool /*convert*/) {
|
bool load(handle src, bool /*convert*/) {
|
||||||
if (!isinstance<T>(src))
|
if (!isinstance<T>(src))
|
||||||
return false;
|
return false;
|
||||||
auto inst = reinterpret_cast<instance *>(src.ptr());
|
auto inst = reinterpret_cast<instance *>(src.ptr());
|
||||||
auto v_h = inst->get_value_and_holder(get_type_info(typeid(T)));
|
loaded_v_h = inst->get_value_and_holder(get_type_info(typeid(T)));
|
||||||
smhldr_ptr = &v_h.holder<pybindit::memory::smart_holder>();
|
if (!loaded_v_h.holder_constructed()) {
|
||||||
|
// IMPROVEABLE: Error message.
|
||||||
|
throw std::runtime_error("Missing value for wrapped C++ type:"
|
||||||
|
" Python instance is uninitialized or was disowned.");
|
||||||
|
}
|
||||||
|
loaded_smhldr_ptr = &loaded_v_h.holder<holder_type>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<T> loaded_as_unique_ptr() {
|
||||||
|
void *value_void_ptr = loaded_v_h.value_ptr();
|
||||||
|
auto unq_ptr = loaded_smhldr_ptr->as_unique_ptr<mpty>();
|
||||||
|
loaded_v_h.holder<holder_type>().~holder_type();
|
||||||
|
loaded_v_h.set_holder_constructed(false);
|
||||||
|
loaded_v_h.value_ptr() = nullptr;
|
||||||
|
deregister_instance(loaded_v_h.inst, value_void_ptr, loaded_v_h.type);
|
||||||
|
return unq_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
pybindit::memory::smart_holder *smhldr_ptr = nullptr;
|
value_and_holder loaded_v_h;
|
||||||
|
holder_type *loaded_smhldr_ptr = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -127,12 +145,12 @@ struct type_caster<mpty> : smart_holder_type_caster_load<mpty> {
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
operator mpty() { return smhldr_ptr->lvalue_ref<mpty>(); }
|
operator mpty() { return loaded_smhldr_ptr->lvalue_ref<mpty>(); }
|
||||||
operator mpty&&() && { return smhldr_ptr->rvalue_ref<mpty>(); }
|
operator mpty&&() && { return loaded_smhldr_ptr->rvalue_ref<mpty>(); }
|
||||||
operator mpty const&() { return smhldr_ptr->lvalue_ref<mpty>(); }
|
operator mpty const&() { return loaded_smhldr_ptr->lvalue_ref<mpty>(); }
|
||||||
operator mpty&() { return smhldr_ptr->lvalue_ref<mpty>(); }
|
operator mpty&() { return loaded_smhldr_ptr->lvalue_ref<mpty>(); }
|
||||||
operator mpty const*() { return smhldr_ptr->as_raw_ptr_unowned<mpty>(); }
|
operator mpty const*() { return loaded_smhldr_ptr->as_raw_ptr_unowned<mpty>(); }
|
||||||
operator mpty*() { return smhldr_ptr->as_raw_ptr_unowned<mpty>(); }
|
operator mpty*() { return loaded_smhldr_ptr->as_raw_ptr_unowned<mpty>(); }
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@ -331,7 +349,7 @@ struct type_caster<std::shared_ptr<mpty>> : smart_holder_type_caster_load<mpty>
|
|||||||
template <typename>
|
template <typename>
|
||||||
using cast_op_type = std::shared_ptr<mpty>;
|
using cast_op_type = std::shared_ptr<mpty>;
|
||||||
|
|
||||||
operator std::shared_ptr<mpty>() { return smhldr_ptr->as_shared_ptr<mpty>(); }
|
operator std::shared_ptr<mpty>() { return loaded_smhldr_ptr->as_shared_ptr<mpty>(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -349,7 +367,7 @@ struct type_caster<std::shared_ptr<mpty const>> : smart_holder_type_caster_load<
|
|||||||
template <typename>
|
template <typename>
|
||||||
using cast_op_type = std::shared_ptr<mpty const>;
|
using cast_op_type = std::shared_ptr<mpty const>;
|
||||||
|
|
||||||
operator std::shared_ptr<mpty const>() { return smhldr_ptr->as_shared_ptr<mpty>(); }
|
operator std::shared_ptr<mpty const>() { return loaded_smhldr_ptr->as_shared_ptr<mpty>(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -398,10 +416,7 @@ struct type_caster<std::unique_ptr<mpty>> : smart_holder_type_caster_load<mpty>
|
|||||||
template <typename>
|
template <typename>
|
||||||
using cast_op_type = std::unique_ptr<mpty>;
|
using cast_op_type = std::unique_ptr<mpty>;
|
||||||
|
|
||||||
operator std::unique_ptr<mpty>() {
|
operator std::unique_ptr<mpty>() { return loaded_as_unique_ptr(); }
|
||||||
// MISSING: value_and_holder value_ptr reset, deregister_instance.
|
|
||||||
return smhldr_ptr->as_unique_ptr<mpty>();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@ -419,10 +434,7 @@ struct type_caster<std::unique_ptr<mpty const>> : smart_holder_type_caster_load<
|
|||||||
template <typename>
|
template <typename>
|
||||||
using cast_op_type = std::unique_ptr<mpty const>;
|
using cast_op_type = std::unique_ptr<mpty const>;
|
||||||
|
|
||||||
operator std::unique_ptr<mpty const>() {
|
operator std::unique_ptr<mpty const>() { return loaded_as_unique_ptr(); }
|
||||||
// MISSING: value_and_holder value_ptr reset, deregister_instance.
|
|
||||||
return smhldr_ptr->as_unique_ptr<mpty>();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
@ -466,7 +478,10 @@ TEST_SUBMODULE(classh_wip, m) {
|
|||||||
m.def("pass_mpty_uqmp", pass_mpty_uqmp);
|
m.def("pass_mpty_uqmp", pass_mpty_uqmp);
|
||||||
m.def("pass_mpty_uqcp", pass_mpty_uqcp);
|
m.def("pass_mpty_uqcp", pass_mpty_uqcp);
|
||||||
|
|
||||||
m.def("get_mtxt", get_mtxt); // Requires pass_mpty_cref to work properly.
|
// Helpers, these require selected functions above to work, as indicated:
|
||||||
|
m.def("get_mtxt", get_mtxt); // pass_mpty_cref
|
||||||
|
m.def("unique_ptr_roundtrip",
|
||||||
|
[](std::unique_ptr<mpty> obj) { return obj; }); // pass_mpty_uqmp, rtrn_mpty_uqmp
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace classh_wip
|
} // namespace classh_wip
|
||||||
|
@ -63,4 +63,14 @@ def test_pass_unique_ptr_disowns(pass_mpty, argm, rtrn):
|
|||||||
assert pass_mpty(obj) == rtrn
|
assert pass_mpty(obj) == rtrn
|
||||||
with pytest.raises(RuntimeError) as exc_info:
|
with pytest.raises(RuntimeError) as exc_info:
|
||||||
m.pass_mpty_uqmp(obj)
|
m.pass_mpty_uqmp(obj)
|
||||||
assert str(exc_info.value) == "Cannot disown nullptr (as_unique_ptr)."
|
assert str(exc_info.value) == (
|
||||||
|
"Missing value for wrapped C++ type:"
|
||||||
|
" Python instance is uninitialized or was disowned."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_unique_ptr_roundtrip(num_round_trips=1000):
|
||||||
|
recycled = m.mpty("passenger")
|
||||||
|
for _ in range(num_round_trips):
|
||||||
|
recycled = m.unique_ptr_roundtrip(recycled)
|
||||||
|
assert m.get_mtxt(recycled) == "passenger"
|
||||||
|
Loading…
Reference in New Issue
Block a user