From 509506955b694279a8ed94b825223cd78f8ac133 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Tue, 14 Jun 2022 12:22:11 -0700 Subject: [PATCH] VERY MESSY SNAPSHOT of WIP, this was the starting point for cl/454658864, which has more changes on top. --- include/pybind11/cast.h | 64 +++++++++++++++---- include/pybind11/chrono.h | 2 + include/pybind11/complex.h | 1 + include/pybind11/detail/init.h | 1 + .../detail/smart_holder_type_casters.h | 5 ++ include/pybind11/detail/type_caster_base.h | 1 + include/pybind11/eigen.h | 4 ++ include/pybind11/functional.h | 1 + include/pybind11/numpy.h | 1 + include/pybind11/stl.h | 6 ++ include/pybind11/stl/filesystem.h | 1 + tests/pybind11_tests.h | 1 + tests/test_async.cpp | 28 ++++---- tests/test_async.py | 15 ++++- tests/test_buffers.cpp | 30 +++++---- tests/test_buffers.py | 15 ++++- tests/test_builtin_casters.cpp | 1 + tests/test_copy_move.cpp | 3 + tests/test_custom_type_casters.cpp | 5 ++ 19 files changed, 144 insertions(+), 41 deletions(-) diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 1ac42038d..256775bf7 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -47,30 +47,60 @@ class type_caster_for_class_ : public type_caster_base {}; template class type_caster : public type_caster_for_class_ {}; -inline std::unordered_map &odr_guard_registry() { - static std::unordered_map reg; +inline std::unordered_map &odr_guard_registry() { + static std::unordered_map reg; return reg; } +namespace { + +template +bool odr_guard_impl(const std::type_index & it_ti, const std::uint64_t& tc_id) { + auto match = odr_guard_registry().find(it_ti); + printf("\nLOOOK %s %llu\n", type_id().c_str(), (long long) tc_id); + fflush(stdout); + if (match == odr_guard_registry().end()) { + odr_guard_registry().insert({it_ti, tc_id}); + } else if (match->second != tc_id) { + throw std::system_error(std::make_error_code(std::errc::state_not_recoverable), + "pybind11::detail::type_caster<" + type_id() + + "> ODR VIOLATION DETECTED"); + } + return true; +} + template struct type_caster_odr_guard : type_caster { type_caster_odr_guard() { - auto it_ti = std::type_index(typeid(IntrinsicType)); - auto tc_ti = std::type_index(typeid(type_caster)); - auto match = odr_guard_registry().find(it_ti); - if (match == odr_guard_registry().end()) { - odr_guard_registry().insert({it_ti, tc_ti}); - } else if (match->second != tc_ti) { - throw std::system_error(std::make_error_code(std::errc::state_not_recoverable), - "pybind11::detail::type_caster<" + type_id() - + "> ODR VIOLATION DETECTED"); - } + odr_guard_hook = !!odr_guard_hook; } + + // type_caster_odr_guard(const type_caster_odr_guard &) = default; + // type_caster_odr_guard(type_caster_odr_guard &&) = default; + + template + static handle cast(CType &&src, return_value_policy policy, handle parent, + Arg &&...arg) { + odr_guard_hook = !!odr_guard_hook; + return type_caster::cast(std::forward(src), policy, parent, + std::forward(arg)...); + } + + static bool odr_guard_hook; }; +template +bool type_caster_odr_guard::odr_guard_hook = [](){ + return odr_guard_impl( + std::type_index(typeid(IntrinsicType)), + type_caster::universally_unique_identifier); +}(); + template using make_caster = type_caster_odr_guard>; +} // namespace + template struct type_uses_smart_holder_type_caster { static constexpr bool value @@ -106,6 +136,7 @@ private: public: bool load(handle src, bool convert) { return subcaster.load(src, convert); } static constexpr auto name = caster_t::name; + static constexpr std::uint64_t universally_unique_identifier = 1655073597; static handle cast(const std::reference_wrapper &src, return_value_policy policy, handle parent) { // It is definitely wrong to take ownership of this pointer, so mask that rvp @@ -277,6 +308,7 @@ public: } PYBIND11_TYPE_CASTER(T, const_name::value>("int", "float")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; template @@ -292,6 +324,7 @@ public: return none().inc_ref(); } PYBIND11_TYPE_CASTER(T, const_name("None")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; template <> @@ -339,6 +372,7 @@ public: using cast_op_type = void *&; explicit operator void *&() { return value; } static constexpr auto name = const_name("capsule"); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; private: void *value = nullptr; @@ -395,6 +429,7 @@ public: return handle(src ? Py_True : Py_False).inc_ref(); } PYBIND11_TYPE_CASTER(bool, const_name("bool")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; // Helper class for UTF-{8,16,32} C++ stl strings: @@ -487,6 +522,7 @@ struct string_caster { } PYBIND11_TYPE_CASTER(StringType, const_name(PYBIND11_STRING_NAME)); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; private: static handle decode_utfN(const char *buffer, ssize_t nbytes) { @@ -659,6 +695,7 @@ public: } static constexpr auto name = const_name(PYBIND11_STRING_NAME); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; template using cast_op_type = pybind11::detail::cast_op_type<_T>; }; @@ -703,6 +740,7 @@ public: static constexpr auto name = const_name("Tuple[") + concat(make_caster::name...) + const_name("]"); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; template using cast_op_type = type; @@ -875,6 +913,7 @@ struct move_only_holder_caster { return type_caster_base::cast_holder(ptr, std::addressof(src)); } static constexpr auto name = type_caster_base::name; + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; #ifndef PYBIND11_USE_SMART_HOLDER_AS_DEFAULT @@ -984,6 +1023,7 @@ struct pyobject_caster { return src.inc_ref(); } PYBIND11_TYPE_CASTER(type, handle_type_name::name); + static constexpr std::uint64_t universally_unique_identifier = 3434; }; template diff --git a/include/pybind11/chrono.h b/include/pybind11/chrono.h index 167ea0e3d..6342f0ab6 100644 --- a/include/pybind11/chrono.h +++ b/include/pybind11/chrono.h @@ -97,6 +97,7 @@ public: } PYBIND11_TYPE_CASTER(type, const_name("datetime.timedelta")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) { @@ -208,6 +209,7 @@ public: us.count()); } PYBIND11_TYPE_CASTER(type, const_name("datetime.datetime")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; // Other clocks that are not the system clock are not measured as datetime.datetime objects diff --git a/include/pybind11/complex.h b/include/pybind11/complex.h index 8a831c12c..118f7073e 100644 --- a/include/pybind11/complex.h +++ b/include/pybind11/complex.h @@ -69,6 +69,7 @@ public: } PYBIND11_TYPE_CASTER(std::complex, const_name("complex")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; PYBIND11_NAMESPACE_END(detail) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) diff --git a/include/pybind11/detail/init.h b/include/pybind11/detail/init.h index 18adc40b1..8e383e48d 100644 --- a/include/pybind11/detail/init.h +++ b/include/pybind11/detail/init.h @@ -27,6 +27,7 @@ public: using cast_op_type = value_and_holder &; explicit operator value_and_holder &() { return *value; } static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; private: value_and_holder *value = nullptr; diff --git a/include/pybind11/detail/smart_holder_type_casters.h b/include/pybind11/detail/smart_holder_type_casters.h index 52b37d591..dedfad0a1 100644 --- a/include/pybind11/detail/smart_holder_type_casters.h +++ b/include/pybind11/detail/smart_holder_type_casters.h @@ -616,6 +616,7 @@ template struct smart_holder_type_caster : smart_holder_type_caster_load, smart_holder_type_caster_class_hooks { static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; // static handle cast(T, ...) // is redundant (leads to ambiguous overloads). @@ -777,6 +778,7 @@ template struct smart_holder_type_caster> : smart_holder_type_caster_load, smart_holder_type_caster_class_hooks { static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; static handle cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { switch (policy) { @@ -841,6 +843,7 @@ template struct smart_holder_type_caster> : smart_holder_type_caster_load, smart_holder_type_caster_class_hooks { static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; static handle cast(const std::shared_ptr &src, return_value_policy policy, handle parent) { @@ -861,6 +864,7 @@ template struct smart_holder_type_caster> : smart_holder_type_caster_load, smart_holder_type_caster_class_hooks { static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { if (policy != return_value_policy::automatic @@ -944,6 +948,7 @@ template struct smart_holder_type_caster> : smart_holder_type_caster_load, smart_holder_type_caster_class_hooks { static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; static handle cast(std::unique_ptr &&src, return_value_policy policy, handle parent) { diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h index 777fbb716..3e2590bf9 100644 --- a/include/pybind11/detail/type_caster_base.h +++ b/include/pybind11/detail/type_caster_base.h @@ -911,6 +911,7 @@ class type_caster_base : public type_caster_generic { public: static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; type_caster_base() : type_caster_base(typeid(type)) {} explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) {} diff --git a/include/pybind11/eigen.h b/include/pybind11/eigen.h index beb50266e..41dd2496c 100644 --- a/include/pybind11/eigen.h +++ b/include/pybind11/eigen.h @@ -392,6 +392,7 @@ public: } static constexpr auto name = props::descriptor; + static constexpr std::uint64_t universally_unique_identifier = 1655073597; // NOLINTNEXTLINE(google-explicit-constructor) operator Type *() { return &value; } @@ -436,6 +437,7 @@ public: } static constexpr auto name = props::descriptor; + static constexpr std::uint64_t universally_unique_identifier = 1655073597; // Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return // types but not bound arguments). We still provide them (with an explicitly delete) so that @@ -623,6 +625,7 @@ public: } static constexpr auto name = props::descriptor; + static constexpr std::uint64_t universally_unique_identifier = 1655073597; // Explicitly delete these: support python -> C++ conversion on these (i.e. these can be return // types but not bound arguments). We still provide them (with an explicitly delete) so that @@ -699,6 +702,7 @@ struct type_caster::value>> { const_name<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[") + npy_format_descriptor::name + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; PYBIND11_NAMESPACE_END(detail) diff --git a/include/pybind11/functional.h b/include/pybind11/functional.h index 4034990d8..8c4e3d5ea 100644 --- a/include/pybind11/functional.h +++ b/include/pybind11/functional.h @@ -124,6 +124,7 @@ public: const_name("Callable[[") + concat(make_caster::name...) + const_name("], ") + make_caster::name + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; PYBIND11_NAMESPACE_END(detail) diff --git a/include/pybind11/numpy.h b/include/pybind11/numpy.h index 0291b02d0..6611387ce 100644 --- a/include/pybind11/numpy.h +++ b/include/pybind11/numpy.h @@ -1214,6 +1214,7 @@ struct pyobject_caster> { return src.inc_ref(); } PYBIND11_TYPE_CASTER(type, handle_type_name::name); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; template diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index ab30ecac0..351b28d6c 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -87,6 +87,7 @@ struct set_caster { } PYBIND11_TYPE_CASTER(type, const_name("Set[") + key_conv::name + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; template @@ -136,6 +137,7 @@ struct map_caster { PYBIND11_TYPE_CASTER(Type, const_name("Dict[") + key_conv::name + const_name(", ") + value_conv::name + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; template @@ -188,6 +190,7 @@ public: } PYBIND11_TYPE_CASTER(Type, const_name("List[") + value_conv::name + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; template @@ -257,6 +260,7 @@ public: const_name("[") + const_name() + const_name("]")) + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; template @@ -315,6 +319,7 @@ struct optional_caster { } PYBIND11_TYPE_CASTER(Type, const_name("Optional[") + value_conv::name + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; #if defined(PYBIND11_HAS_OPTIONAL) @@ -401,6 +406,7 @@ struct variant_caster> { PYBIND11_TYPE_CASTER(Type, const_name("Union[") + detail::concat(make_caster::name...) + const_name("]")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; #if defined(PYBIND11_HAS_VARIANT) diff --git a/include/pybind11/stl/filesystem.h b/include/pybind11/stl/filesystem.h index e26f42177..c5ac3faab 100644 --- a/include/pybind11/stl/filesystem.h +++ b/include/pybind11/stl/filesystem.h @@ -99,6 +99,7 @@ public: } PYBIND11_TYPE_CASTER(T, const_name("os.PathLike")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; }; #endif // PYBIND11_HAS_FILESYSTEM || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM) diff --git a/tests/pybind11_tests.h b/tests/pybind11_tests.h index a7c00c2f9..7ddd6c837 100644 --- a/tests/pybind11_tests.h +++ b/tests/pybind11_tests.h @@ -61,6 +61,7 @@ template <> class type_caster { public: PYBIND11_TYPE_CASTER(RValueCaster, const_name("RValueCaster")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; static handle cast(RValueCaster &&, return_value_policy, handle) { return py::str("rvalue").release(); } diff --git a/tests/test_async.cpp b/tests/test_async.cpp index 833022c54..9de494709 100644 --- a/tests/test_async.cpp +++ b/tests/test_async.cpp @@ -9,29 +9,32 @@ #include "pybind11_tests.h" +#define USE_MRC_AAA +#ifdef USE_MRC_AAA namespace mrc_ns { // minimal real caster -struct minimal_real_caster; - +template struct type_mrc { int value = -9999; }; +template struct minimal_real_caster { - static constexpr auto name = py::detail::const_name(); + static constexpr auto name = py::detail::const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1000000; static py::handle - cast(type_mrc const &src, py::return_value_policy /*policy*/, py::handle /*parent*/) { + cast(CType const &src, py::return_value_policy /*policy*/, py::handle /*parent*/) { return py::int_(src.value + 1010).release(); } // Maximizing simplicity. This will go terribly wrong for other arg types. template - using cast_op_type = const type_mrc &; + using cast_op_type = const CType &; // NOLINTNEXTLINE(google-explicit-constructor) - operator type_mrc const &() { - static type_mrc obj; + operator CType const &() { + static CType obj; obj.value = 11; return obj; } @@ -46,10 +49,11 @@ struct minimal_real_caster { namespace pybind11 { namespace detail { -template <> -struct type_caster : mrc_ns::minimal_real_caster {}; +template +struct type_caster> : mrc_ns::minimal_real_caster> {}; } // namespace detail } // namespace pybind11 +#endif TEST_SUBMODULE(async_module, m) { struct DoesNotSupportAsync {}; @@ -64,6 +68,8 @@ TEST_SUBMODULE(async_module, m) { f.attr("set_result")(5); return f.attr("__await__")(); }); - m.def("type_mrc_to_python", []() { return mrc_ns::type_mrc{101}; }); - m.def("type_mrc_from_python", [](const mrc_ns::type_mrc &obj) { return obj.value + 100; }); +#ifdef USE_MRC_AAA + m.def("type_mrc_to_python", []() { return mrc_ns::type_mrc{101}; }); + m.def("type_mrc_from_python", [](const mrc_ns::type_mrc &obj) { return obj.value + 100; }); +#endif } diff --git a/tests/test_async.py b/tests/test_async.py index c33d2113e..ca185fa9f 100644 --- a/tests/test_async.py +++ b/tests/test_async.py @@ -24,6 +24,15 @@ def test_await_missing(event_loop): event_loop.run_until_complete(get_await_result(m.DoesNotSupportAsync())) -def test_mrc(): - assert m.type_mrc_to_python() == 1111 - assert m.type_mrc_from_python("ignored") == 111 +def test_type_mrc_to_python(): + if hasattr(m, "type_mrc_to_python"): + assert m.type_mrc_to_python() == 1111 + else: + pytype.skip("type_mrc_to_python") + + +def test_type_mrc_from_python(): + if hasattr(m, "type_mrc_from_python"): + assert m.type_mrc_from_python("ignored") == 111 + else: + pytype.skip("type_mrc_from_python") diff --git a/tests/test_buffers.cpp b/tests/test_buffers.cpp index f1a134282..258086003 100644 --- a/tests/test_buffers.cpp +++ b/tests/test_buffers.cpp @@ -12,29 +12,32 @@ #include "constructor_stats.h" #include "pybind11_tests.h" +#define USE_MRC_BBB +#ifdef USE_MRC_BBB namespace mrc_ns { // minimal real caster -struct minimal_real_caster; - +template struct type_mrc { - int value = -9999; + ValType value = -9999; }; +template struct minimal_real_caster { - static constexpr auto name = py::detail::const_name(); + static constexpr auto name = py::detail::const_name(); + static constexpr std::uint64_t universally_unique_identifier = 2000000; static py::handle - cast(type_mrc const &src, py::return_value_policy /*policy*/, py::handle /*parent*/) { + cast(CType const &src, py::return_value_policy /*policy*/, py::handle /*parent*/) { return py::int_(src.value + 2020).release(); } // Maximizing simplicity. This will go terribly wrong for other arg types. template - using cast_op_type = const type_mrc &; + using cast_op_type = const CType &; // NOLINTNEXTLINE(google-explicit-constructor) - operator type_mrc const &() { - static type_mrc obj; + operator CType const &() { + static CType obj; obj.value = 22; return obj; } @@ -49,10 +52,11 @@ struct minimal_real_caster { namespace pybind11 { namespace detail { -template <> -struct type_caster : mrc_ns::minimal_real_caster {}; +template +struct type_caster> : mrc_ns::minimal_real_caster> {}; } // namespace detail } // namespace pybind11 +#endif TEST_SUBMODULE(buffers, m) { // test_from_python / test_to_python: @@ -264,6 +268,8 @@ TEST_SUBMODULE(buffers, m) { m.def("get_buffer_info", [](const py::buffer &buffer) { return buffer.request(); }); - m.def("type_mrc_to_python", []() { return mrc_ns::type_mrc{202}; }); - m.def("type_mrc_from_python", [](const mrc_ns::type_mrc &obj) { return obj.value + 200; }); +#ifdef USE_MRC_BBB + m.def("type_mrc_to_python", []() { return mrc_ns::type_mrc{202}; }); + m.def("type_mrc_from_python", [](const mrc_ns::type_mrc &obj) { return obj.value + 200; }); +#endif } diff --git a/tests/test_buffers.py b/tests/test_buffers.py index 515af4b10..35b97c38e 100644 --- a/tests/test_buffers.py +++ b/tests/test_buffers.py @@ -163,6 +163,15 @@ def test_ctypes_from_buffer(): assert not cinfo.readonly -def test_mrc(): - assert m.type_mrc_to_python() == 1111 - assert m.type_mrc_from_python("ignored") == 111 +def test_type_mrc_to_python(): + if hasattr(m, "type_mrc_to_python"): + assert m.type_mrc_to_python() == 2222 + else: + pytype.skip("type_mrc_to_python") + + +def test_type_mrc_from_python(): + if hasattr(m, "type_mrc_from_python"): + assert m.type_mrc_from_python("ignored") == 222 + else: + pytype.skip("type_mrc_from_python") diff --git a/tests/test_builtin_casters.cpp b/tests/test_builtin_casters.cpp index 9c0ec73f6..b063599f1 100644 --- a/tests/test_builtin_casters.cpp +++ b/tests/test_builtin_casters.cpp @@ -28,6 +28,7 @@ template <> class type_caster { public: static constexpr auto name = const_name(); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; // Input is unimportant, a new value will always be constructed based on the // cast operator. diff --git a/tests/test_copy_move.cpp b/tests/test_copy_move.cpp index 28c244564..5cd9d8550 100644 --- a/tests/test_copy_move.cpp +++ b/tests/test_copy_move.cpp @@ -106,6 +106,7 @@ PYBIND11_NAMESPACE_BEGIN(detail) template <> struct type_caster { PYBIND11_TYPE_CASTER(MoveOnlyInt, const_name("MoveOnlyInt")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(handle src, bool) { value = MoveOnlyInt(src.cast()); return true; @@ -118,6 +119,7 @@ struct type_caster { template <> struct type_caster { PYBIND11_TYPE_CASTER(MoveOrCopyInt, const_name("MoveOrCopyInt")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(handle src, bool) { value = MoveOrCopyInt(src.cast()); return true; @@ -134,6 +136,7 @@ protected: public: static constexpr auto name = const_name("CopyOnlyInt"); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(handle src, bool) { value = CopyOnlyInt(src.cast()); return true; diff --git a/tests/test_custom_type_casters.cpp b/tests/test_custom_type_casters.cpp index 25540e368..911b30c35 100644 --- a/tests/test_custom_type_casters.cpp +++ b/tests/test_custom_type_casters.cpp @@ -32,6 +32,7 @@ public: #else PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1")); #endif + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(handle src, bool convert) { value.arg = "loading ArgInspector1 argument " + std::string(convert ? "WITH" : "WITHOUT") @@ -49,6 +50,7 @@ template <> struct type_caster { public: PYBIND11_TYPE_CASTER(ArgInspector2, const_name("ArgInspector2")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(handle src, bool convert) { value.arg = "loading ArgInspector2 argument " + std::string(convert ? "WITH" : "WITHOUT") @@ -66,6 +68,7 @@ template <> struct type_caster { public: PYBIND11_TYPE_CASTER(ArgAlwaysConverts, const_name("ArgAlwaysConverts")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(handle, bool convert) { return convert; } @@ -97,6 +100,7 @@ namespace detail { template <> struct type_caster { PYBIND11_TYPE_CASTER(DestructionTester, const_name("DestructionTester")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(handle, bool) { return true; } static handle cast(const DestructionTester &, return_value_policy, handle) { @@ -119,6 +123,7 @@ namespace py_ = ::pybind11; // don't have any symbol collision when using macro mixin. struct my_caster { PYBIND11_TYPE_CASTER(MyType, py_::detail::const_name("MyType")); + static constexpr std::uint64_t universally_unique_identifier = 1655073597; bool load(py_::handle, bool) { return true; } static py_::handle cast(const MyType &, py_::return_value_policy, py_::handle) {