ChimeraTK-ApplicationCore 04.06.00
Loading...
Searching...
No Matches
PythonBindings.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4#include <pybind11/pybind11.h>
5// pybind11.h must come first
6
7#include "Application.h"
9#include "PyArrayAccessor.h"
10#include "PyConfigReader.h"
12#include "PyLogger.h"
13#include "PyModuleGroup.h"
15#include "PyReadAnyGroup.h"
16#include "PyScalarAccessor.h"
18#include "PyVariableGroup.h"
19#include "PyVoidAccessor.h"
20
21#include <ChimeraTK/DataConsistencyGroup.h>
22#include <ChimeraTK/SupportedUserTypes.h>
23#include <ChimeraTK/VariantUserTypes.h>
24
25#include <pybind11/chrono.h>
26#include <pybind11/operators.h>
27#include <pybind11/pytypes.h>
28#include <pybind11/stl.h>
29
30#include <boost/fusion/algorithm.hpp>
31#include <boost/fusion/container/map.hpp>
32
33#include <iostream>
34#include <map>
35#include <string>
36#include <variant>
37
38namespace py = pybind11;
39using namespace py::literals;
40
47namespace ChimeraTK {
48
51 if(Application::hasInstance()) { // hasInstance check required for stubgen tool (it doesn't instantiate an app)
52 // We assume here that the reason for PyApplicationCore lib unload is application shutdown.
53 // We need to deinitialize PythonModuleManager early in order to get back global interpreter lock.
54 // Some static library deinitialsers (in particular exception object used by pybind11 register_exception)
55 // assume that we own the GIL.
56 // The PythonModuleManager will also shut down all PyApplicationModules (i.e. their internal threads) while
57 // keeping the rest of the Application intact for now.
58 Application::getInstance().getPythonModuleManager().deinit();
59 }
60 }
61 };
69 template<class UnloadHook>
70 static void registerUnloadHook() {
71 static UnloadHook hook;
72 }
73
74 /********************************************************************************************************************/
75
76 PYBIND11_MODULE(PyApplicationCore, m) {
80 py::register_exception<ChimeraTK::logic_error>(m, "LogicError", PyExc_RuntimeError);
81
85 py::class_<DataType> mDataType(m, "DataType");
86 mDataType.def(py::init<DataType::TheType>())
87 .def("__str__", &DataType::getAsString)
88 .def(py::self == py::self)
89 .def("__repr__", [](const DataType& type) { return "DataType." + type.getAsString(); });
90 py::enum_<DataType::TheType>(mDataType, "TheType")
91 .value("none", DataType::none)
92 .value("int8", DataType::int8)
93 .value("uint8", DataType::uint8)
94 .value("int16", DataType::int16)
95 .value("uint16", DataType::uint16)
96 .value("int32", DataType::int32)
97 .value("uint32", DataType::uint32)
98 .value("int64", DataType::int64)
99 .value("uint64", DataType::uint64)
100 .value("float32", DataType::float32)
101 .value("float64", DataType::float64)
102 .value("string", DataType::string)
103 .value("Boolean", DataType::Boolean)
104 .value("Void", DataType::Void)
105 .export_values();
106 py::implicitly_convertible<DataType::TheType, DataType>();
107 py::implicitly_convertible<DataType, DataType::TheType>();
108
112 py::enum_<DataValidity>(m, "DataValidity")
113 .value("ok", DataValidity::ok)
114 .value("faulty", DataValidity::faulty)
115 .export_values();
116
120 py::class_<VersionNumber>(m, "VersionNumber")
121 .def(py::init<>())
122 .def(py::init<std::chrono::system_clock::time_point>())
123 .def(py::init<std::nullptr_t>(), py::arg("version").none(true))
124 // NOLINTBEGIN(misc-redundant-expression)
125 .def(py::self == py::self)
126 .def(py::self != py::self)
127 .def(py::self < py::self)
128 .def(py::self <= py::self)
129 .def(py::self > py::self)
130 .def(py::self >= py::self)
131 // NOLINTEND(misc-redundant-expression)
132 .def("getTime", &VersionNumber::getTime, R"(Return the time stamp associated with this version number.)")
133 .def("__str__", [](VersionNumber& v) { return std::string(v); })
134 .def("__repr__", [](VersionNumber& v) { return "VersionNumber(" + std::string(v) + ")"; });
135
139 py::class_<Boolean>(m, "Boolean")
140 .def(py::init<>())
141 .def(py::init<bool>())
142 // NOLINTBEGIN(misc-redundant-expression)
143 .def(py::self == py::self)
144 .def(py::self != py::self)
145 // NOLINTEND(misc-redundant-expression)
146 .def("__bool__", [](Boolean& v) { return bool(v); })
147 .def("__repr__", [](Boolean& v) { return "Boolean(" + std::to_string(bool(v)) + ")"; })
148 .def("__int__", [](Boolean& v) { return int(bool(v)); })
149 .def("__str__", [](Boolean& v) { return std::format("{}", bool(v)); });
150
154 py::class_<TransferElementID>(m, "TransferElementID")
155 .def(py::init<>())
156 // NOLINTBEGIN(misc-redundant-expression)
157 .def(py::self == py::self)
158 .def(py::self != py::self)
159 // NOLINTEND(misc-redundant-expression)
160 .def("isValid", &TransferElementID::isValid, R"(Check whether the ID is valid.)")
161 .def("__str__",
162 [](TransferElementID& id) {
163 std::stringstream ss;
164 ss << id;
165 return ss.str();
166 })
167 .def("__repr__", [](TransferElementID& id) {
168 std::stringstream ss;
169 ss << id;
170 return "TransferElementID(" + ss.str() + ")";
171 });
172
177 py::class_<PyOwnedObject> pwnedObject(m, "PyOwnedObject");
178 py::class_<PyOwningObject> pwningObject(m, "PyOwningObject");
179
188
193
198
203
208
213
218
223
228
233
238
243
244 /*
245 * Set the main ModuleGroup as an attribute of the bindings module. This is done with a callback to avoid
246 * problems with the symbol visibility (all pybind11 classes are hidden, so we cannot pass them directly between
247 * the bindings .so and the main library .so).
248 */
250 Application::getInstance().getPythonModuleManager().setOnMainGroupChange(
251 [m](const std::unique_ptr<PyModuleGroup>& mainGroup) {
252 m.attr("app") = py::cast(mainGroup.get(), py::return_value_policy::reference);
253 });
254 }
255
256 registerUnloadHook<PyApplicationCoreUnload>();
257 }
258
259 /********************************************************************************************************************/
260
261} // namespace ChimeraTK
static Application & getInstance()
Obtain instance of the application.
static bool hasInstance()
Check whether an instance of Application currently exists.
Definition Application.h:96
static void bind(py::module &mod)
static void bind(py::module &mod)
static void bind(py::module &mod)
static void bind(py::module &mod)
Definition PyLogger.cc:12
static void bind(pybind11::module &mod)
static void bind(py::module &mod)
static void bind(py::module &mod)
static void bind(py::module &mod)
static void bind(py::module &mod)
static void bind(py::module &m)
static void bind(py::module &mod)
InvalidityTracer application module.
PYBIND11_MODULE(PyApplicationCore, m)