From 1ef19a1e047b1e06563f501a61e212837515f366 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sun, 17 Jan 2021 13:19:48 -0800 Subject: [PATCH] Using pybind11/detail/classh_type_casters.h from test_classh_wip.cpp. --- include/pybind11/classh.h | 1 + include/pybind11/detail/classh_type_casters.h | 137 ++++--- tests/test_classh_wip.cpp | 363 +----------------- 3 files changed, 83 insertions(+), 418 deletions(-) diff --git a/include/pybind11/classh.h b/include/pybind11/classh.h index 16b5242b7..a23468f6f 100644 --- a/include/pybind11/classh.h +++ b/include/pybind11/classh.h @@ -1,5 +1,6 @@ #pragma once +#include "detail/classh_type_casters.h" #include "pybind11.h" #include "smart_holder_poc.h" diff --git a/include/pybind11/detail/classh_type_casters.h b/include/pybind11/detail/classh_type_casters.h index d26e0f100..a3708ab30 100644 --- a/include/pybind11/detail/classh_type_casters.h +++ b/include/pybind11/detail/classh_type_casters.h @@ -1,8 +1,20 @@ +#pragma once + +#include "../pytypes.h" +#include "../smart_holder_poc.h" +#include "common.h" +#include "descr.h" +#include "internals.h" + +#include +#include +#include +#include +#include + namespace pybind11 { namespace detail { -using namespace pybind11_tests::classh_wip; - inline std::pair find_existing_python_instance(void *src_void_ptr, const detail::type_info *tinfo) { // Loop copied from type_caster_generic::cast. @@ -38,7 +50,7 @@ struct smart_holder_type_caster_load { std::unique_ptr loaded_as_unique_ptr() { void *value_void_ptr = loaded_v_h.value_ptr(); - auto unq_ptr = loaded_smhldr_ptr->as_unique_ptr(); + auto unq_ptr = loaded_smhldr_ptr->as_unique_ptr(); loaded_v_h.holder().~holder_type(); loaded_v_h.set_holder_constructed(false); loaded_v_h.value_ptr() = nullptr; @@ -79,14 +91,14 @@ struct make_constructor { // clang-format on // type_caster_base END -template <> -struct type_caster : smart_holder_type_caster_load { - static constexpr auto name = _(); +template +struct classh_type_caster : smart_holder_type_caster_load { + static constexpr auto name = _(); - // static handle cast(mpty, ...) + // static handle cast(T, ...) // is redundant (leads to ambiguous overloads). - static handle cast(mpty &&src, return_value_policy /*policy*/, handle parent) { + static handle cast(T &&src, return_value_policy /*policy*/, handle parent) { // type_caster_base BEGIN // clang-format off return cast(&src, return_value_policy::move, parent); @@ -94,7 +106,7 @@ struct type_caster : smart_holder_type_caster_load { // type_caster_base END } - static handle cast(mpty const &src, return_value_policy policy, handle parent) { + static handle cast(T const &src, return_value_policy policy, handle parent) { // type_caster_base BEGIN // clang-format off if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) @@ -104,12 +116,12 @@ struct type_caster : smart_holder_type_caster_load { // type_caster_base END } - static handle cast(mpty &src, return_value_policy policy, handle parent) { - return cast(const_cast(src), policy, parent); // Mutbl2Const + static handle cast(T &src, return_value_policy policy, handle parent) { + return cast(const_cast(src), policy, parent); // Mutbl2Const } - static handle cast(mpty const *src, return_value_policy policy, handle parent) { - auto st = type_caster_base::src_and_type(src); + static handle cast(T const *src, return_value_policy policy, handle parent) { + auto st = type_caster_base::src_and_type(src); return cast_const_raw_ptr( // Originally type_caster_generic::cast. st.first, policy, @@ -119,32 +131,31 @@ struct type_caster : smart_holder_type_caster_load { make_constructor::make_move_constructor(src)); } - static handle cast(mpty *src, return_value_policy policy, handle parent) { - return cast(const_cast(src), policy, parent); // Mutbl2Const + static handle cast(T *src, return_value_policy policy, handle parent) { + return cast(const_cast(src), policy, parent); // Mutbl2Const } template using cast_op_type = conditional_t< - std::is_same, mpty const *>::value, - mpty const *, + std::is_same, T const *>::value, + T const *, conditional_t< - std::is_same, mpty *>::value, - mpty *, - conditional_t< - std::is_same::value, - mpty const &, - conditional_t::value, - mpty &, - conditional_t::value, mpty &&, mpty>>>>>; + std::is_same, T *>::value, + T *, + conditional_t::value, + T const &, + conditional_t::value, + T &, + conditional_t::value, T &&, T>>>>>; // clang-format off - operator mpty() { return loaded_smhldr_ptr->lvalue_ref(); } - operator mpty&&() && { return loaded_smhldr_ptr->rvalue_ref(); } - operator mpty const&() { return loaded_smhldr_ptr->lvalue_ref(); } - operator mpty&() { return loaded_smhldr_ptr->lvalue_ref(); } - operator mpty const*() { return loaded_smhldr_ptr->as_raw_ptr_unowned(); } - operator mpty*() { return loaded_smhldr_ptr->as_raw_ptr_unowned(); } + operator T() { return this->loaded_smhldr_ptr->template lvalue_ref(); } + operator T&&() && { return this->loaded_smhldr_ptr->template rvalue_ref(); } + operator T const&() { return this->loaded_smhldr_ptr->template lvalue_ref(); } + operator T&() { return this->loaded_smhldr_ptr->template lvalue_ref(); } + operator T const*() { return this->loaded_smhldr_ptr->template as_raw_ptr_unowned(); } + operator T*() { return this->loaded_smhldr_ptr->template as_raw_ptr_unowned(); } // clang-format on @@ -238,12 +249,11 @@ struct type_caster : smart_holder_type_caster_load { } }; -template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); +template +struct classh_type_caster> : smart_holder_type_caster_load { + static constexpr auto name = _>(); - static handle - cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { + static handle cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { if (policy != return_value_policy::automatic && policy != return_value_policy::reference_internal) { // IMPROVEABLE: Error message. @@ -251,7 +261,7 @@ struct type_caster> : smart_holder_type_caster_load } auto src_raw_ptr = src.get(); - auto st = type_caster_base::src_and_type(src_raw_ptr); + auto st = type_caster_base::src_and_type(src_raw_ptr); if (st.first == nullptr) return none().release(); // PyErr was set already. @@ -279,34 +289,36 @@ struct type_caster> : smart_holder_type_caster_load } template - using cast_op_type = std::shared_ptr; + using cast_op_type = std::shared_ptr; - operator std::shared_ptr() { return loaded_smhldr_ptr->as_shared_ptr(); } + operator std::shared_ptr() { return this->loaded_smhldr_ptr->template as_shared_ptr(); } }; -template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); +template +struct classh_type_caster> : smart_holder_type_caster_load { + static constexpr auto name = _>(); static handle - cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { - return type_caster>::cast( - std::const_pointer_cast(src), // Const2Mutbl + cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { + return type_caster>::cast( + std::const_pointer_cast(src), // Const2Mutbl policy, parent); } template - using cast_op_type = std::shared_ptr; + using cast_op_type = std::shared_ptr; - operator std::shared_ptr() { return loaded_smhldr_ptr->as_shared_ptr(); } + operator std::shared_ptr() { + return this->loaded_smhldr_ptr->template as_shared_ptr(); + } }; -template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); +template +struct classh_type_caster> : smart_holder_type_caster_load { + static constexpr auto name = _>(); - static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { + static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { if (policy != return_value_policy::automatic && policy != return_value_policy::reference_internal) { // IMPROVEABLE: Error message. @@ -314,7 +326,7 @@ struct type_caster> : smart_holder_type_caster_load } auto src_raw_ptr = src.get(); - auto st = type_caster_base::src_and_type(src_raw_ptr); + auto st = type_caster_base::src_and_type(src_raw_ptr); if (st.first == nullptr) return none().release(); // PyErr was set already. @@ -340,27 +352,26 @@ struct type_caster> : smart_holder_type_caster_load } template - using cast_op_type = std::unique_ptr; + using cast_op_type = std::unique_ptr; - operator std::unique_ptr() { return loaded_as_unique_ptr(); } + operator std::unique_ptr() { return this->loaded_as_unique_ptr(); } }; -template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); +template +struct classh_type_caster> : smart_holder_type_caster_load { + static constexpr auto name = _>(); - static handle - cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { - return type_caster>::cast( - std::unique_ptr(const_cast(src.release())), // Const2Mutbl + static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { + return type_caster>::cast( + std::unique_ptr(const_cast(src.release())), // Const2Mutbl policy, parent); } template - using cast_op_type = std::unique_ptr; + using cast_op_type = std::unique_ptr; - operator std::unique_ptr() { return loaded_as_unique_ptr(); } + operator std::unique_ptr() { return this->loaded_as_unique_ptr(); } }; } // namespace detail diff --git a/tests/test_classh_wip.cpp b/tests/test_classh_wip.cpp index 62e0b5d95..7bf976fca 100644 --- a/tests/test_classh_wip.cpp +++ b/tests/test_classh_wip.cpp @@ -52,367 +52,20 @@ std::unique_ptr unique_ptr_roundtrip(std::unique_ptr obj) { return o namespace pybind11 { namespace detail { -using namespace pybind11_tests::classh_wip; - -inline std::pair find_existing_python_instance(void *src_void_ptr, - const detail::type_info *tinfo) { - // Loop copied from type_caster_generic::cast. - // IMPROVEABLE: Factor out of type_caster_generic::cast. - auto it_instances = get_internals().registered_instances.equal_range(src_void_ptr); - for (auto it_i = it_instances.first; it_i != it_instances.second; ++it_i) { - for (auto instance_type : detail::all_type_info(Py_TYPE(it_i->second))) { - if (instance_type && same_type(*instance_type->cpptype, *tinfo->cpptype)) - return std::make_pair(true, handle((PyObject *) it_i->second).inc_ref()); - } - } - return std::make_pair(false, handle()); -} - -template -struct smart_holder_type_caster_load { - using holder_type = pybindit::memory::smart_holder; - - bool load(handle src, bool /*convert*/) { - if (!isinstance(src)) - return false; - auto inst = reinterpret_cast(src.ptr()); - loaded_v_h = inst->get_value_and_holder(get_type_info(typeid(T))); - if (!loaded_v_h.holder_constructed()) { - // IMPROVEABLE: Error message. A change to the existing internals is - // needed to cleanly distinguish between uninitialized or disowned. - throw std::runtime_error("Missing value for wrapped C++ type:" - " Python instance is uninitialized or was disowned."); - } - loaded_smhldr_ptr = &loaded_v_h.holder(); - return true; - } - - std::unique_ptr loaded_as_unique_ptr() { - void *value_void_ptr = loaded_v_h.value_ptr(); - auto unq_ptr = loaded_smhldr_ptr->as_unique_ptr(); - loaded_v_h.holder().~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: - value_and_holder loaded_v_h; - holder_type *loaded_smhldr_ptr = nullptr; -}; - -// type_caster_base BEGIN -// clang-format off -// Helper factored out of type_caster_base. -struct make_constructor { - using Constructor = void *(*)(const void *); - - /* Only enabled when the types are {copy,move}-constructible *and* when the type - does not have a private operator new implementation. */ - template ::value>> - static auto make_copy_constructor(const T *x) -> decltype(new T(*x), Constructor{}) { - return [](const void *arg) -> void * { - return new T(*reinterpret_cast(arg)); - }; - } - - template ::value>> - static auto make_move_constructor(const T *x) -> decltype(new T(std::move(*const_cast(x))), Constructor{}) { - return [](const void *arg) -> void * { - return new T(std::move(*const_cast(reinterpret_cast(arg)))); - }; - } - - static Constructor make_copy_constructor(...) { return nullptr; } - static Constructor make_move_constructor(...) { return nullptr; } -}; -// clang-format on -// type_caster_base END +using mpty = pybind11_tests::classh_wip::mpty; template <> -struct type_caster : smart_holder_type_caster_load { - static constexpr auto name = _(); - - // static handle cast(mpty, ...) - // is redundant (leads to ambiguous overloads). - - static handle cast(mpty &&src, return_value_policy /*policy*/, handle parent) { - // type_caster_base BEGIN - // clang-format off - return cast(&src, return_value_policy::move, parent); - // clang-format on - // type_caster_base END - } - - static handle cast(mpty const &src, return_value_policy policy, handle parent) { - // type_caster_base BEGIN - // clang-format off - if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference) - policy = return_value_policy::copy; - return cast(&src, policy, parent); - // clang-format on - // type_caster_base END - } - - static handle cast(mpty &src, return_value_policy policy, handle parent) { - return cast(const_cast(src), policy, parent); // Mutbl2Const - } - - static handle cast(mpty const *src, return_value_policy policy, handle parent) { - auto st = type_caster_base::src_and_type(src); - return cast_const_raw_ptr( // Originally type_caster_generic::cast. - st.first, - policy, - parent, - st.second, - make_constructor::make_copy_constructor(src), - make_constructor::make_move_constructor(src)); - } - - static handle cast(mpty *src, return_value_policy policy, handle parent) { - return cast(const_cast(src), policy, parent); // Mutbl2Const - } - - template - using cast_op_type = conditional_t< - std::is_same, mpty const *>::value, - mpty const *, - conditional_t< - std::is_same, mpty *>::value, - mpty *, - conditional_t< - std::is_same::value, - mpty const &, - conditional_t::value, - mpty &, - conditional_t::value, mpty &&, mpty>>>>>; - - // clang-format off - - operator mpty() { return loaded_smhldr_ptr->lvalue_ref(); } - operator mpty&&() && { return loaded_smhldr_ptr->rvalue_ref(); } - operator mpty const&() { return loaded_smhldr_ptr->lvalue_ref(); } - operator mpty&() { return loaded_smhldr_ptr->lvalue_ref(); } - operator mpty const*() { return loaded_smhldr_ptr->as_raw_ptr_unowned(); } - operator mpty*() { return loaded_smhldr_ptr->as_raw_ptr_unowned(); } - - // clang-format on - - // Originally type_caster_generic::cast. - PYBIND11_NOINLINE static handle cast_const_raw_ptr(const void *_src, - return_value_policy policy, - handle parent, - const detail::type_info *tinfo, - void *(*copy_constructor)(const void *), - void *(*move_constructor)(const void *), - const void *existing_holder = nullptr) { - if (!tinfo) // no type info: error will be set already - return handle(); - - void *src = const_cast(_src); - if (src == nullptr) - return none().release(); - - auto existing_inst = find_existing_python_instance(src, tinfo); - if (existing_inst.first) - return existing_inst.second; - - auto inst = reinterpret_steal(make_new_instance(tinfo->type)); - auto wrapper = reinterpret_cast(inst.ptr()); - wrapper->owned = false; - void *&valueptr = values_and_holders(wrapper).begin()->value_ptr(); - - switch (policy) { - case return_value_policy::automatic: - case return_value_policy::take_ownership: - valueptr = src; - wrapper->owned = true; - break; - - case return_value_policy::automatic_reference: - case return_value_policy::reference: - valueptr = src; - wrapper->owned = false; - break; - - case return_value_policy::copy: - if (copy_constructor) - valueptr = copy_constructor(src); - else { -#if defined(NDEBUG) - throw cast_error("return_value_policy = copy, but type is " - "non-copyable! (compile in debug mode for details)"); -#else - std::string type_name(tinfo->cpptype->name()); - detail::clean_type_id(type_name); - throw cast_error("return_value_policy = copy, but type " + type_name - + " is non-copyable!"); -#endif - } - wrapper->owned = true; - break; - - case return_value_policy::move: - if (move_constructor) - valueptr = move_constructor(src); - else if (copy_constructor) - valueptr = copy_constructor(src); - else { -#if defined(NDEBUG) - throw cast_error("return_value_policy = move, but type is neither " - "movable nor copyable! " - "(compile in debug mode for details)"); -#else - std::string type_name(tinfo->cpptype->name()); - detail::clean_type_id(type_name); - throw cast_error("return_value_policy = move, but type " + type_name - + " is neither movable nor copyable!"); -#endif - } - wrapper->owned = true; - break; - - case return_value_policy::reference_internal: - valueptr = src; - wrapper->owned = false; - keep_alive_impl(inst, parent); - break; - - default: - throw cast_error("unhandled return_value_policy: should not happen!"); - } - - tinfo->init_instance(wrapper, existing_holder); - - return inst.release(); - } -}; - +class type_caster : public classh_type_caster {}; template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); - - static handle - cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { - if (policy != return_value_policy::automatic - && policy != return_value_policy::reference_internal) { - // IMPROVEABLE: Error message. - throw cast_error("Invalid return_value_policy for shared_ptr."); - } - - auto src_raw_ptr = src.get(); - auto st = type_caster_base::src_and_type(src_raw_ptr); - if (st.first == nullptr) - return none().release(); // PyErr was set already. - - void *src_raw_void_ptr = static_cast(src_raw_ptr); - const detail::type_info *tinfo = st.second; - auto existing_inst = find_existing_python_instance(src_raw_void_ptr, tinfo); - if (existing_inst.first) - // MISSING: Enforcement of consistency with existing smart_holder. - // MISSING: keep_alive. - return existing_inst.second; - - object inst = reinterpret_steal(make_new_instance(tinfo->type)); - instance *inst_raw_ptr = reinterpret_cast(inst.ptr()); - inst_raw_ptr->owned = true; - void *&valueptr = values_and_holders(inst_raw_ptr).begin()->value_ptr(); - valueptr = src_raw_void_ptr; - - auto smhldr = pybindit::memory::smart_holder::from_shared_ptr(src); - tinfo->init_instance(inst_raw_ptr, static_cast(&smhldr)); - - if (policy == return_value_policy::reference_internal) - keep_alive_impl(inst, parent); - - return inst.release(); - } - - template - using cast_op_type = std::shared_ptr; - - operator std::shared_ptr() { return loaded_smhldr_ptr->as_shared_ptr(); } -}; - +class type_caster> : public classh_type_caster> {}; template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); - - static handle - cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { - return type_caster>::cast( - std::const_pointer_cast(src), // Const2Mutbl - policy, - parent); - } - - template - using cast_op_type = std::shared_ptr; - - operator std::shared_ptr() { return loaded_smhldr_ptr->as_shared_ptr(); } -}; - +class type_caster> + : public classh_type_caster> {}; template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); - - static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { - if (policy != return_value_policy::automatic - && policy != return_value_policy::reference_internal) { - // IMPROVEABLE: Error message. - throw cast_error("Invalid return_value_policy for unique_ptr."); - } - - auto src_raw_ptr = src.get(); - auto st = type_caster_base::src_and_type(src_raw_ptr); - if (st.first == nullptr) - return none().release(); // PyErr was set already. - - void *src_raw_void_ptr = static_cast(src_raw_ptr); - const detail::type_info *tinfo = st.second; - auto existing_inst = find_existing_python_instance(src_raw_void_ptr, tinfo); - if (existing_inst.first) - throw cast_error("Invalid unique_ptr: another instance owns this pointer already."); - - object inst = reinterpret_steal(make_new_instance(tinfo->type)); - instance *inst_raw_ptr = reinterpret_cast(inst.ptr()); - inst_raw_ptr->owned = true; - void *&valueptr = values_and_holders(inst_raw_ptr).begin()->value_ptr(); - valueptr = src_raw_void_ptr; - - auto smhldr = pybindit::memory::smart_holder::from_unique_ptr(std::move(src)); - tinfo->init_instance(inst_raw_ptr, static_cast(&smhldr)); - - if (policy == return_value_policy::reference_internal) - keep_alive_impl(inst, parent); - - return inst.release(); - } - - template - using cast_op_type = std::unique_ptr; - - operator std::unique_ptr() { return loaded_as_unique_ptr(); } -}; - +class type_caster> : public classh_type_caster> {}; template <> -struct type_caster> : smart_holder_type_caster_load { - static constexpr auto name = _>(); - - static handle - cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { - return type_caster>::cast( - std::unique_ptr(const_cast(src.release())), // Const2Mutbl - policy, - parent); - } - - template - using cast_op_type = std::unique_ptr; - - operator std::unique_ptr() { return loaded_as_unique_ptr(); } -}; +class type_caster> + : public classh_type_caster> {}; } // namespace detail } // namespace pybind11