converter.h
Go to the documentation of this file.
1 // FROM
2 // https://github.com/drodri/cppcon2016/blob/master/pythoncpp/boost/converter.h
4 
5 #include <boost/python.hpp>
6 #include <boost/python/suite/indexing/map_indexing_suite.hpp>
7 
8 namespace wrappers {
9 namespace py = boost::python;
10 template <typename T>
11 auto getItem(T& obj, int64_t index) -> decltype(obj[0]) {
12  if (index < 0) {
13  index += obj.size();
14  }
15  if (index >= 0 && size_t(index) < obj.size()) {
16  return obj[size_t(index)];
17  }
18  PyErr_SetString(PyExc_IndexError, "index out of range");
19  py::throw_error_already_set();
20  return obj[0];
21 }
22 
23 template <typename T, typename ValT>
24 void setItem(T& obj, int64_t index, ValT value) {
25  if (index < 0) {
26  index += obj.size();
27  }
28  if (index >= 0 && size_t(index) < obj.size()) {
29  obj[size_t(index)] = value;
30  return;
31  }
32  PyErr_SetString(PyExc_IndexError, "index out of range");
33  py::throw_error_already_set();
34 }
35 
36 template <typename T>
37 void delItem(T& obj, int64_t index) {
38  if (index < 0) {
39  index += obj.size();
40  }
41  if (index >= 0 && size_t(index) < obj.size()) {
42  obj.erase(std::next(obj.begin(), index));
43  return;
44  }
45  PyErr_SetString(PyExc_IndexError, "index out of range");
46  py::throw_error_already_set();
47 }
48 } // namespace wrappers
49 
50 namespace converters {
51 namespace py = boost::python;
52 
56  template <typename Container>
58  boost::python::converter::registry::push_back(
59  &IterableConverter::convertible, &IterableConverter::construct<Container>, boost::python::type_id<Container>());
60 
61  // Support chaining.
62  return *this;
63  }
64 
66  static void* convertible(PyObject* object) {
67  auto* it = PyObject_GetIter(object);
68  if (it != nullptr) {
69  Py_DECREF(it);
70  return object;
71  }
72  if (PyErr_ExceptionMatches(PyExc_TypeError) != 0) {
73  PyErr_Clear();
74  }
75  return nullptr;
76  }
77 
85  template <typename Container>
86  static void construct(PyObject* object, boost::python::converter::rvalue_from_python_stage1_data* data) {
87  namespace python = boost::python;
88  // Object is a borrowed reference, so create a handle indicting it is
89  // borrowed for proper reference counting.
90  python::handle<> handle(python::borrowed(object));
91 
92  // Obtain a handle to the memory block that the converter has allocated
93  // for the C++ type.
94  using StorageType = python::converter::rvalue_from_python_storage<Container>;
95  void* storage = reinterpret_cast<StorageType*>(data)->storage.bytes; // NOLINT
96 
97  using Iterator = python::stl_input_iterator<typename Container::value_type>;
98 
99  // Allocate the C++ type into the converter's memory block, and assign
100  // its handle to the converter's convertible variable. The C++
101  // container is populated by passing the begin and end iterators of
102  // the python object to the container's constructor.
103  new (storage) Container(Iterator(python::object(handle)), // begin
104  Iterator()); // end
105  data->convertible = storage;
106  }
107 };
111  template <typename OptionalT>
113  boost::python::converter::registry::push_back(&ToOptionalConverter::convertible,
114  &ToOptionalConverter::construct<OptionalT>,
115  boost::python::type_id<lanelet::Optional<OptionalT>>());
116  // Support chaining.
117  return *this;
118  }
119 
121  static void* convertible(PyObject* object) { return object; }
122 
124  template <typename OptionalT>
125  static void construct(PyObject* object, boost::python::converter::rvalue_from_python_stage1_data* data) {
126  namespace python = boost::python;
127  using StorageType = python::converter::rvalue_from_python_storage<lanelet::Optional<OptionalT>>;
128  void* storage = reinterpret_cast<StorageType*>(data)->storage.bytes; // NOLINT
129 
130  if (object == Py_None) {
131  new (storage) lanelet::Optional<OptionalT>();
132  } else {
133  new (storage) lanelet::Optional<OptionalT>(python::extract<OptionalT>(object));
134  }
135  data->convertible = storage;
136  }
137 };
138 
139 template <typename T>
140 struct VariantToObject : boost::static_visitor<PyObject*> {
141  static result_type convert(const T& v) { return apply_visitor(VariantToObject(), v); }
142 
143  template <typename Type>
144  result_type operator()(const Type& t) const {
145  return boost::python::incref(boost::python::object(t).ptr());
146  }
147 };
148 
149 template <typename T>
150 struct VectorToList {
151  static PyObject* convert(const T& v) {
152  py::list l;
153  for (auto& e : v) {
154  l.append(e);
155  }
156  return py::incref(l.ptr());
157  }
158 };
159 
160 template <typename T>
162  static PyObject* convert(const lanelet::Optional<T>& v) {
163  if (v) {
164  return py::incref(py::object(v.get()).ptr());
165  }
166  // return none
167  return py::incref(py::object().ptr());
168  }
169 };
170 
171 template <typename T>
172 struct WeakToObject {
173  static PyObject* convert(const T& v) {
174  if (!v.expired()) {
175  return py::incref(py::object(v.lock()).ptr());
176  }
177  // return none
178  return py::incref(py::object().ptr());
179  }
180 };
181 
182 template <typename T1, typename T2>
184  static PyObject* convert(const std::pair<T1, T2>& pair) {
185  return py::incref(py::make_tuple(pair.first, pair.second).ptr());
186  }
187 };
188 
189 template <typename T1, typename T2>
192  py::converter::registry::push_back(&convertible, &construct, py::type_id<std::pair<T1, T2>>());
193  }
194  static void* convertible(PyObject* obj) {
195  if (!PyTuple_CheckExact(obj)) {
196  return nullptr;
197  }
198  if (PyTuple_Size(obj) != 2) {
199  return nullptr;
200  }
201  return obj;
202  }
203  static void construct(PyObject* obj, py::converter::rvalue_from_python_stage1_data* data) {
204  py::tuple tuple(py::borrowed(obj));
205  using StorageType = py::converter::rvalue_from_python_storage<std::pair<T1, T2>>;
206  void* storage = reinterpret_cast<StorageType*>(data)->storage.bytes; // NOLINT
207  new (storage) std::pair<T1, T2>(py::extract<T1>(tuple[0])(), py::extract<T2>(tuple[1])());
208  data->convertible = storage;
209  }
210 };
211 
212 template <typename T1, typename T2>
213 struct PyPair {
214  py::to_python_converter<std::pair<T1, T2>, PairToPythonConverter<T1, T2>> toPy;
216 };
217 
218 template <typename T>
219 using VectorToListConverter = py::to_python_converter<T, VectorToList<T>>;
220 
221 template <typename T>
222 using OptionalConverter = py::to_python_converter<lanelet::Optional<T>, OptionalToObject<T>>;
223 
224 template <typename T>
225 using WeakConverter = py::to_python_converter<T, WeakToObject<T>>;
226 
227 template <typename T>
228 using VariantConverter = py::to_python_converter<T, VariantToObject<T>>;
229 
230 template <typename T>
232 } // namespace converters
converters::VariantToObject
Definition: converter.h:140
converters::VectorToList
Definition: converter.h:150
converters::ToOptionalConverter
Definition: converter.h:108
converters::ToOptionalConverter::convertible
static void * convertible(PyObject *object)
Check PyObject.
Definition: converter.h:121
converters::OptionalToObject
Definition: converter.h:161
converters::VariantToObject::convert
static result_type convert(const T &v)
Definition: converter.h:141
converters::PythonToPairConverter::convertible
static void * convertible(PyObject *obj)
Definition: converter.h:194
converters::ToOptionalConverter::construct
static void construct(PyObject *object, boost::python::converter::rvalue_from_python_stage1_data *data)
Convert PyObject to C++ type.
Definition: converter.h:125
converters::IterableConverter::construct
static void construct(PyObject *object, boost::python::converter::rvalue_from_python_stage1_data *data)
Convert iterable PyObject to C++ container type.
Definition: converter.h:86
converters::PythonToPairConverter::PythonToPairConverter
PythonToPairConverter()
Definition: converter.h:191
converters::VariantConverter
py::to_python_converter< T, VariantToObject< T > > VariantConverter
Definition: converter.h:228
converters::PairToPythonConverter
Definition: converter.h:183
converters::PairToPythonConverter::convert
static PyObject * convert(const std::pair< T1, T2 > &pair)
Definition: converter.h:184
converters::PythonToPairConverter
Definition: converter.h:190
lanelet::Optional
boost::optional< T > Optional
converters::VariantToObject::operator()
result_type operator()(const Type &t) const
Definition: converter.h:144
converters::IterableConverter::fromPython
IterableConverter & fromPython()
Definition: converter.h:57
converters::PyPair::toPy
py::to_python_converter< std::pair< T1, T2 >, PairToPythonConverter< T1, T2 > > toPy
Definition: converter.h:214
converters::PythonToPairConverter::construct
static void construct(PyObject *obj, py::converter::rvalue_from_python_stage1_data *data)
Definition: converter.h:203
wrappers::setItem
void setItem(T &obj, int64_t index, ValT value)
Definition: converter.h:24
converters
Definition: converter.h:50
wrappers
Definition: converter.h:8
converters::VectorToListConverter
py::to_python_converter< T, VectorToList< T > > VectorToListConverter
Definition: converter.h:219
converters::IterableConverter::convertible
static void * convertible(PyObject *object)
Check if PyObject is iterable.
Definition: converter.h:66
converters::WeakToObject
Definition: converter.h:172
wrappers::delItem
void delItem(T &obj, int64_t index)
Definition: converter.h:37
wrappers::getItem
auto getItem(T &obj, int64_t index) -> decltype(obj[0])
Definition: converter.h:11
converters::OptionalToObject::convert
static PyObject * convert(const lanelet::Optional< T > &v)
Definition: converter.h:162
converters::WeakToObject::convert
static PyObject * convert(const T &v)
Definition: converter.h:173
converters::ToOptionalConverter::fromPython
ToOptionalConverter & fromPython()
Definition: converter.h:112
converters::WeakConverter
py::to_python_converter< T, WeakToObject< T > > WeakConverter
Definition: converter.h:225
converters::PyPair
Definition: converter.h:213
Optional.h
converters::IterableConverter
Definition: converter.h:53
converters::OptionalConverter
py::to_python_converter< lanelet::Optional< T >, OptionalToObject< T > > OptionalConverter
Definition: converter.h:222
converters::PyPair::fromPy
PythonToPairConverter< T1, T2 > fromPy
Definition: converter.h:215
converters::VectorToList::convert
static PyObject * convert(const T &v)
Definition: converter.h:151


lanelet2_python
Author(s): Fabian Poggenhans
autogenerated on Thu Mar 6 2025 03:26:14