optional.hpp
Go to the documentation of this file.
1 
7 #ifndef __eigenpy_optional_hpp__
8 #define __eigenpy_optional_hpp__
9 
10 #include "eigenpy/fwd.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 
23 namespace boost {
24 namespace python {
25 namespace converter {
26 
27 template <typename T>
28 struct expected_pytype_for_arg<boost::optional<T> >
29  : expected_pytype_for_arg<T> {};
30 
31 #ifdef EIGENPY_WITH_CXX17_SUPPORT
32 template <typename T>
33 struct 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 
41 namespace eigenpy {
42 
43 namespace detail {
44 
47 template <template <typename> class OptionalTpl>
48 struct nullopt_helper {};
49 
50 template <>
51 struct 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
57 template <>
58 struct nullopt_helper<std::optional> {
59  typedef std::nullopt_t type;
60  static type value() { return std::nullopt; }
61 };
62 #endif
63 
64 template <typename NoneType>
65 struct NoneToPython {
66  static PyObject *convert(const NoneType &) { Py_RETURN_NONE; }
67 
68  static void registration() {
69  if (!check_registration<NoneType>()) {
70  bp::to_python_converter<NoneType, NoneToPython, false>();
71  }
72  }
73 };
74 
75 template <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 
97 template <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 
108 template <typename T, template <typename> class OptionalTpl>
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 
120 template <typename T, template <typename> class OptionalTpl>
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 
140 template <typename T, template <typename> class OptionalTpl>
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 
151 template <typename T,
152  template <typename> class OptionalTpl = EIGENPY_DEFAULT_OPTIONAL>
154  static void registration() {
157  }
158 };
159 
160 } // namespace eigenpy
161 
162 #endif // __eigenpy_optional_hpp__
EIGENPY_DEFAULT_OPTIONAL
#define EIGENPY_DEFAULT_OPTIONAL
Definition: optional.hpp:20
eigenpy::detail::NoneToPython::convert
static PyObject * convert(const NoneType &)
Definition: optional.hpp:66
eigenpy::OptionalConverter
Definition: optional.hpp:153
eigenpy::detail::OptionalToPython::registration
static void registration()
Definition: optional.hpp:90
registration.hpp
eigenpy::detail::OptionalFromPython::construct
static void construct(PyObject *obj_ptr, bp::converter::rvalue_from_python_stage1_data *memory)
Definition: optional.hpp:121
eigenpy::detail::OptionalFromPython
Definition: optional.hpp:99
fwd.hpp
eigen-from-python.hpp
boost
Definition: alignment.hpp:48
eigenpy::detail::OptionalFromPython::convertible
static void * convertible(PyObject *obj_ptr)
Definition: optional.hpp:109
eigenpy
Definition: alignment.hpp:14
eigenpy::check_registration
bool check_registration()
Check at runtime the registration of the type T inside the boost python registry.
Definition: registration.hpp:23
eigenpy::detail::nullopt_helper< boost::optional >::value
static type value()
Definition: optional.hpp:53
python
Definition: python.py:1
eigenpy::detail::OptionalToPython::convert
static PyObject * convert(const OptionalTpl< T > &obj)
Definition: optional.hpp:78
test_matrix.value
float value
Definition: test_matrix.py:161
eigenpy::detail::OptionalFromPython::registration
static void registration()
Definition: optional.hpp:141
eigenpy::detail::nullopt_helper
Definition: optional.hpp:48
eigenpy::detail::OptionalToPython
Definition: optional.hpp:77
eigenpy::detail::NoneToPython
Definition: optional.hpp:65
eigenpy::detail::OptionalToPython::get_pytype
static const PyTypeObject * get_pytype()
Definition: optional.hpp:86
eigenpy::detail::NoneToPython::registration
static void registration()
Definition: optional.hpp:68
eigenpy::detail::nullopt_helper< boost::optional >::type
boost::none_t type
Definition: optional.hpp:52
eigenpy::OptionalConverter::registration
static void registration()
Definition: optional.hpp:154


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Tue Jan 23 2024 03:15:01