1212#include " Acts/Utilities/HashedString.hpp"
1313
1414#include < concepts>
15- #include < cstdint>
1615#include < functional>
17- #include < memory>
18- #include < typeinfo>
16+ #include < unordered_map>
1917
2018#include < pybind11/pybind11.h>
2119
@@ -45,72 +43,50 @@ concept PyClassWithSmartHolder =
4543class WhiteBoardRegistry {
4644 private:
4745 // / Function that converts a type-erased pointer from the WhiteBoard into a
48- // / pybind11 object. The wbPy argument is used for reference_internal
49- // / lifetime.
50- using ToPythonFunction = std::function<pybind11::object(
51- const Acts::AnyMoveOnly& any, const pybind11::object& wbPy)>;
46+ // / Python object.
47+ using ToPythonFunction =
48+ std::function<PyObject*(const Acts::AnyMoveOnly& any, PyObject* wbPy)>;
5249
53- // / Function that converts a pybind11 object into a type-erased pointer for
54- // / the WhiteBoard.
55- using FromPythonFunction = std::function<std::unique_ptr<Acts::AnyMoveOnly>(
56- const pybind11::object& obj)>;
50+ // / Function that converts a Python object into a type-erased holder for the
51+ // / WhiteBoard.
52+ using FromPythonFunction =
53+ std::function<std::unique_ptr<Acts::AnyMoveOnly>(PyObject* obj)>;
5754
58- public:
59- // / Opaque handle to an internal registry entry.
60- struct EntryHandle {
61- protected:
62- EntryHandle () = default ;
63- ~EntryHandle () = default ;
64- };
65-
66- private:
67- static void registerTypeImpl (PyObject* pyType, ToPythonFunction toPython,
68- FromPythonFunction fromPython,
69- const std::type_info* typeinfo,
70- std::uint64_t typeHash);
71-
72- public:
73- // / Register a C++ type T with its pybind11 Python type for WhiteBoard
74- // / access. Use when the `py::class_<T>` type cannot be deduced (e.g. for
75- // / template types).
76- // / @tparam T The C++ type to register.
7755 template <typename T>
7856 static void registerType () {
7957 namespace py = pybind11;
8058 return registerType<T>(py::type::of<T>());
8159 }
8260
83- // / Register a C++ type `~T` with its pybind11 Python type for WhiteBoard
84- // / access. Use when the `py::class_<T>` type cannot be deduced (e.g. for
85- // / template types).
86- // / @tparam T The C++ type to register.
87- // / @param pyType The pybind11 Python type object to register.
8861 template <typename T>
8962 static void registerType (const pybind11::object& pyType) {
9063 namespace py = pybind11;
9164
9265 using type = T;
9366
94- registerTypeImpl (
95- pyType.ptr (),
96- [](const Acts::AnyMoveOnly& any, const py::object& wbPy) -> py::object {
97- // wb needed to ensure correct lifetime
98- return py::cast (any.as <type>(),
99- py::return_value_policy::reference_internal, wbPy);
100- },
101- [](const py::object& obj) {
102- // This communicates to pybind11's smart_holder that the object is
103- // consumed in C++
104- auto up = py::cast<std::unique_ptr<T>>(obj);
105- return std::make_unique<Acts::AnyMoveOnly>(std::move (*up));
67+ instance ()[pyType.ptr ()] = {
68+ .toPython = [](const Acts::AnyMoveOnly& any,
69+ PyObject* wbPy) -> PyObject* {
70+ py::object pyWb = py::reinterpret_borrow<py::object>(wbPy);
71+ py::object out =
72+ py::cast (any.as <type>(),
73+ py::return_value_policy::reference_internal, pyWb);
74+ return out.release ().ptr ();
10675 },
107- &typeid (type), Acts::typeHash<type>());
76+ .fromPython =
77+ [](PyObject* obj) {
78+ py::object pyObj = py::reinterpret_borrow<py::object>(obj);
79+ // This communicates to pybind11's smart_holder that the object is
80+ // consumed in C++
81+ auto up = py::cast<std::unique_ptr<T>>(pyObj);
82+ return std::make_unique<Acts::AnyMoveOnly>(std::move (*up));
83+ },
84+ .typeinfo = &typeid (type),
85+ .typeHash = Acts::typeHash<type>(),
86+ };
10887 }
10988
110- // / Register a pybind11-bound type T for WhiteBoard read access.
111- // / Call this after the `py::class_<T>` definition.
112- // / @tparam Ts The types to register.
113- // / @param pyClass The pybind11 class object to register.
89+ public:
11490 template <typename ... Ts>
11591 static void registerClass (const pybind11::class_<Ts...>& pyClass)
11692 requires PyClassWithSmartHolder<Ts...>
@@ -119,28 +95,24 @@ class WhiteBoardRegistry {
11995 registerType<type>(pyClass);
12096 }
12197
122- // / Look up a registered type by Python type object.
123- // / @param pyType The Python type object to look up.
124- // / @return Opaque handle to the internal entry, or nullptr if not registered.
125- static const EntryHandle* find (PyObject* pyType) noexcept ;
126-
127- // / Access the registered C++ type metadata.
128- static const std::type_info* typeInfo (const EntryHandle* entry) noexcept ;
129-
130- // / Access the registered hash for runtime type verification.
131- static std::uint64_t typeHash (const EntryHandle* entry) noexcept ;
132-
133- // / Convert a WhiteBoard object into a Python object.
134- // / @return New reference (`PyObject*`) owned by the caller.
135- static PyObject* toPython (const EntryHandle* entry,
136- const Acts::AnyMoveOnly& any, PyObject* wbPy);
98+ struct RegistryEntry {
99+ ToPythonFunction toPython{nullptr };
100+ FromPythonFunction fromPython{nullptr };
101+ const std::type_info* typeinfo{nullptr };
102+ std::uint64_t typeHash{0 };
103+ };
137104
138- // / Convert a Python object into a WhiteBoard-storable holder.
139- static std::unique_ptr<Acts::AnyMoveOnly> fromPython (const EntryHandle* entry,
140- PyObject* obj);
105+ static RegistryEntry* find (const pybind11::object& pyType) {
106+ if (auto it = instance ().find (pyType.ptr ()); it != instance ().end ()) {
107+ return &it->second ;
108+ }
109+ return nullptr ;
110+ }
141111
142112 private:
143113 WhiteBoardRegistry () = default ;
114+
115+ static std::unordered_map<PyObject*, RegistryEntry>& instance ();
144116};
145117
146118} // namespace ActsPython
0 commit comments