eigenpy 3.12.0
Bindings between Numpy and Eigen using Boost.Python
Loading...
Searching...
No Matches
optional.hpp
1
6
7#ifndef __eigenpy_optional_hpp__
8#define __eigenpy_optional_hpp__
9
10#include "eigenpy/fwd.hpp"
11#include "eigenpy/eigen-from-python.hpp"
12#include "eigenpy/registration.hpp"
13
14#include <boost/optional.hpp>
15#ifdef EIGENPY_WITH_CXX17_SUPPORT
16#include <optional>
17#endif
18
19#ifndef EIGENPY_DEFAULT_OPTIONAL
20#define EIGENPY_DEFAULT_OPTIONAL boost::optional
21#endif
22
23namespace boost {
24namespace python {
25namespace converter {
26
27template <typename T>
28struct expected_pytype_for_arg<boost::optional<T>>
29 : expected_pytype_for_arg<T> {};
30
31#ifdef EIGENPY_WITH_CXX17_SUPPORT
32template <typename T>
33struct expected_pytype_for_arg<std::optional<T>> : expected_pytype_for_arg<T> {
34};
35#endif
36
37} // namespace converter
38} // namespace python
39} // namespace boost
40
41namespace eigenpy {
42
43namespace detail {
44
47template <template <typename> class OptionalTpl>
48struct nullopt_helper {};
49
50template <>
51struct nullopt_helper<boost::optional> {
52 typedef boost::none_t type;
53 static type value() { return boost::none; }
54};
55
56#ifdef EIGENPY_WITH_CXX17_SUPPORT
57template <>
58struct nullopt_helper<std::optional> {
59 typedef std::nullopt_t type;
60 static type value() { return std::nullopt; }
61};
62#endif
63
64template <typename NoneType>
66 static PyObject *convert(const NoneType &) { Py_RETURN_NONE; }
67
68 static void registration() {
70 bp::to_python_converter<NoneType, NoneToPython, false>();
71 }
72 }
73};
74
75template <typename T,
76 template <typename> class OptionalTpl = EIGENPY_DEFAULT_OPTIONAL>
78 static PyObject *convert(const OptionalTpl<T> &obj) {
79 if (obj)
80 return bp::incref(bp::object(*obj).ptr());
81 else {
82 return bp::incref(bp::object().ptr()); // None
83 }
84 }
85
86 static PyTypeObject const *get_pytype() {
87 return bp::converter::registered_pytype<T>::get_pytype();
88 }
89
90 static void registration() {
91 if (!check_registration<OptionalTpl<T>>()) {
92 bp::to_python_converter<OptionalTpl<T>, OptionalToPython, true>();
93 }
94 }
95};
96
97template <typename T,
98 template <typename> class OptionalTpl = EIGENPY_DEFAULT_OPTIONAL>
100 static void *convertible(PyObject *obj_ptr);
101
102 static void construct(PyObject *obj_ptr,
103 bp::converter::rvalue_from_python_stage1_data *memory);
104
105 static void registration();
106};
107
108template <typename T, template <typename> class OptionalTpl>
109void *OptionalFromPython<T, OptionalTpl>::convertible(PyObject *obj_ptr) {
110 if (obj_ptr == Py_None) {
111 return obj_ptr;
112 }
113 bp::extract<T> bp_obj(obj_ptr);
114 if (!bp_obj.check())
115 return 0;
116 else
117 return obj_ptr;
118}
119
120template <typename T, template <typename> class OptionalTpl>
121void OptionalFromPython<T, OptionalTpl>::construct(
122 PyObject *obj_ptr, bp::converter::rvalue_from_python_stage1_data *memory) {
123 // create storage
124 using rvalue_storage_t =
125 bp::converter::rvalue_from_python_storage<OptionalTpl<T>>;
126 void *storage =
127 reinterpret_cast<rvalue_storage_t *>(reinterpret_cast<void *>(memory))
128 ->storage.bytes;
129
130 if (obj_ptr == Py_None) {
131 new (storage) OptionalTpl<T>(nullopt_helper<OptionalTpl>::value());
132 } else {
133 const T value = bp::extract<T>(obj_ptr);
134 new (storage) OptionalTpl<T>(value);
135 }
136
137 memory->convertible = storage;
138}
139
140template <typename T, template <typename> class OptionalTpl>
141void OptionalFromPython<T, OptionalTpl>::registration() {
142 bp::converter::registry::push_back(
143 &convertible, &construct, bp::type_id<OptionalTpl<T>>(),
144 bp::converter::expected_pytype_for_arg<OptionalTpl<T>>::get_pytype);
145}
146
147} // namespace detail
148
151template <typename T,
152 template <typename> class OptionalTpl = EIGENPY_DEFAULT_OPTIONAL>
154 static void registration() {
155 detail::OptionalToPython<T, OptionalTpl>::registration();
156 detail::OptionalFromPython<T, OptionalTpl>::registration();
157 }
158};
159
160} // namespace eigenpy
161
162#endif // __eigenpy_optional_hpp__
bool check_registration()
Check at runtime the registration of the type T inside the boost python registry.