std-vector.hpp
Go to the documentation of this file.
1 
6 #ifndef __eigenpy_utils_std_vector_hpp__
7 #define __eigenpy_utils_std_vector_hpp__
8 
9 #include <boost/mpl/if.hpp>
10 #include <boost/python.hpp>
11 #include <boost/python/stl_iterator.hpp>
12 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
13 #include <iterator>
14 #include <string>
15 #include <vector>
16 
17 #include "eigenpy/eigenpy.hpp"
18 #include "eigenpy/config.hpp"
19 #include "eigenpy/copyable.hpp"
22 #include "eigenpy/registration.hpp"
23 
24 namespace eigenpy {
25 // Forward declaration
26 template <typename vector_type, bool NoProxy = false>
28 
29 namespace details {
30 
32 template <typename T>
33 bool from_python_list(PyObject *obj_ptr, T *) {
34  // Check if it is a list
35  if (!PyList_Check(obj_ptr)) return false;
36 
37  // Retrieve the underlying list
38  bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
39  bp::list bp_list(bp_obj);
40  bp::ssize_t list_size = bp::len(bp_list);
41 
42  // Check if all the elements contained in the current vector is of type T
43  for (bp::ssize_t k = 0; k < list_size; ++k) {
44  bp::extract<T> elt(bp_list[k]);
45  if (!elt.check()) return false;
46  }
47 
48  return true;
49 }
50 
51 template <typename vector_type, bool NoProxy>
52 struct build_list {
53  static ::boost::python::list run(vector_type &vec) {
54  bp::list bp_list;
55  for (size_t k = 0; k < vec.size(); ++k) {
56  bp_list.append(boost::ref(vec[k]));
57  }
58  return bp_list;
59  }
60 };
61 
62 template <typename vector_type>
63 struct build_list<vector_type, true> {
64  static ::boost::python::list run(vector_type &vec) {
65  typedef bp::iterator<vector_type> iterator;
66  return bp::list(iterator()(vec));
67  }
68 };
69 
73 template <typename Container>
75  : public boost::python::def_visitor<
76  overload_base_get_item_for_std_vector<Container> > {
77  typedef typename Container::value_type value_type;
78  typedef typename Container::value_type data_type;
79  typedef size_t index_type;
80 
81  template <class Class>
82  void visit(Class &cl) const {
83  cl.def("__getitem__", &base_get_item);
84  }
85 
86  private:
87  static boost::python::object base_get_item(
88  boost::python::back_reference<Container &> container, PyObject *i_) {
89  index_type idx = convert_index(container.get(), i_);
90  typename Container::iterator i = container.get().begin();
91  std::advance(i, idx);
92  if (i == container.get().end()) {
93  PyErr_SetString(PyExc_KeyError, "Invalid index");
94  bp::throw_error_already_set();
95  }
96 
97  typename bp::to_python_indirect<data_type &,
98  bp::detail::make_reference_holder>
99  convert;
100  return bp::object(bp::handle<>(convert(*i)));
101  }
102 
103  static index_type convert_index(Container &container, PyObject *i_) {
104  bp::extract<long> i(i_);
105  if (i.check()) {
106  long index = i();
107  if (index < 0) index += (long)container.size();
108  if (index >= long(container.size()) || index < 0) {
109  PyErr_SetString(PyExc_IndexError, "Index out of range");
110  bp::throw_error_already_set();
111  }
112  return (index_type)index;
113  }
114 
115  PyErr_SetString(PyExc_TypeError, "Invalid index type");
116  bp::throw_error_already_set();
117  return index_type();
118  }
119 };
120 } // namespace details
121 } // namespace eigenpy
122 
123 namespace boost {
124 namespace python {
125 
126 template <typename MatrixType>
128  : converter::extract_rvalue<Eigen::Ref<MatrixType> > {
129  typedef Eigen::Ref<MatrixType> RefType;
130 
131  protected:
132  typedef converter::extract_rvalue<RefType> base;
133 
134  public:
135  typedef RefType result_type;
136 
137  operator result_type() const { return (*this)(); }
138 
139  extract_to_eigen_ref(PyObject *o) : base(o) {}
140  extract_to_eigen_ref(api::object const &o) : base(o.ptr()) {}
141 };
142 
145 template <typename Scalar, int Rows, int Cols, int Options, int MaxRows,
146  int MaxCols>
147 struct extract<Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &>
149  Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > {
150  typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>
153  extract(PyObject *o) : base(o) {}
154  extract(api::object const &o) : base(o.ptr()) {}
155 };
156 
157 template <typename Derived>
158 struct extract<Eigen::MatrixBase<Derived> &>
159  : extract_to_eigen_ref<Eigen::MatrixBase<Derived> > {
160  typedef Eigen::MatrixBase<Derived> MatrixType;
162  extract(PyObject *o) : base(o) {}
163  extract(api::object const &o) : base(o.ptr()) {}
164 };
165 
166 template <typename Derived>
167 struct extract<Eigen::RefBase<Derived> &>
168  : extract_to_eigen_ref<Eigen::RefBase<Derived> > {
169  typedef Eigen::RefBase<Derived> MatrixType;
171  extract(PyObject *o) : base(o) {}
172  extract(api::object const &o) : base(o.ptr()) {}
173 };
174 
175 namespace converter {
176 
177 template <typename Type, class Allocator>
178 struct reference_arg_from_python<std::vector<Type, Allocator> &>
179  : arg_lvalue_from_python_base {
180  typedef std::vector<Type, Allocator> vector_type;
181  typedef vector_type &ref_vector_type;
182  typedef ref_vector_type result_type;
183  typedef extract<Type &> extract_type;
184 
185  reference_arg_from_python(PyObject *py_obj)
186  : arg_lvalue_from_python_base(converter::get_lvalue_from_python(
187  py_obj, registered<vector_type>::converters)),
188  m_data(NULL),
189  m_source(py_obj),
190  vec_ptr(NULL) {
191  if (result() != 0) // we have found a lvalue converter
192  return;
193 
194  // Check if py_obj is a py_list, which can then be converted to an
195  // std::vector
196  bool is_convertible =
197  ::eigenpy::details::from_python_list(py_obj, (Type *)(0));
198  if (!is_convertible) return;
199 
200  typedef ::eigenpy::StdContainerFromPythonList<vector_type> Constructor;
201  Constructor::construct(py_obj, &m_data.stage1);
202 
203  void *&m_result = const_cast<void *&>(result());
204  m_result = m_data.stage1.convertible;
205  vec_ptr = reinterpret_cast<vector_type *>(m_data.storage.bytes);
206  }
207 
208  result_type operator()() const {
209  return ::boost::python::detail::void_ptr_to_reference(result(),
210  (result_type(*)())0);
211  }
212 
214  if (m_data.stage1.convertible == m_data.storage.bytes) {
215  // Copy back the reference
216  const vector_type &vec = *vec_ptr;
217  list bp_list(handle<>(borrowed(m_source)));
218  for (size_t i = 0; i < vec.size(); ++i) {
219  typename extract_type::result_type elt = extract_type(bp_list[i]);
220  elt = vec[i];
221  }
222  }
223  }
224 
225  private:
226  rvalue_from_python_data<ref_vector_type> m_data;
227  PyObject *m_source;
228  vector_type *vec_ptr;
229 };
230 
231 } // namespace converter
232 } // namespace python
233 } // namespace boost
234 
235 namespace eigenpy {
236 
242 template <typename vector_type, bool NoProxy>
243 struct StdContainerFromPythonList {
244  typedef typename vector_type::value_type T;
245  typedef typename vector_type::allocator_type Allocator;
246 
248  static void *convertible(PyObject *obj_ptr) {
249  namespace bp = boost::python;
250 
251  // Check if it is a list
252  if (!PyList_Check(obj_ptr)) return 0;
253 
254  // Retrieve the underlying list
255  bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
256  bp::list bp_list(bp_obj);
257  bp::ssize_t list_size = bp::len(bp_list);
258 
259  // Check if all the elements contained in the current vector is of type T
260  for (bp::ssize_t k = 0; k < list_size; ++k) {
261  bp::extract<T> elt(bp_list[k]);
262  if (!elt.check()) return 0;
263  }
264 
265  return obj_ptr;
266  }
267 
270  static void construct(
271  PyObject *obj_ptr,
272  boost::python::converter::rvalue_from_python_stage1_data *memory) {
273  // Extract the list
274  bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
275  bp::list bp_list(bp_obj);
276 
277  void *storage =
278  reinterpret_cast<
279  bp::converter::rvalue_from_python_storage<vector_type> *>(
280  reinterpret_cast<void *>(memory))
281  ->storage.bytes;
282 
283  typedef bp::stl_input_iterator<T> iterator;
284 
285  // Build the std::vector
286  new (storage) vector_type(iterator(bp_list), iterator());
287 
288  // Validate the construction
289  memory->convertible = storage;
290  }
291 
292  static void register_converter() {
293  ::boost::python::converter::registry::push_back(
294  &convertible, &construct, ::boost::python::type_id<vector_type>());
295  }
296 
297  static ::boost::python::list tolist(vector_type &self) {
299  }
300 };
301 
302 namespace internal {
303 
304 template <typename T>
306  : boost::mpl::if_<typename boost::is_base_of<Eigen::EigenBase<T>, T>::type,
307  has_operator_equal<Eigen::EigenBase<T> >,
308  boost::true_type>::type {};
309 
310 template <typename T, class A>
311 struct has_operator_equal<std::vector<T, A> > : has_operator_equal<T> {};
312 
313 template <>
314 struct has_operator_equal<bool> : boost::true_type {};
315 
316 template <typename EigenObject>
317 struct has_operator_equal<Eigen::EigenBase<EigenObject> >
318  : has_operator_equal<typename EigenObject::Scalar> {};
319 
320 template <typename T, bool has_operator_equal_value = boost::is_base_of<
321  boost::true_type, has_operator_equal<T> >::value>
323 
324 template <typename T>
325 struct contains_algo<T, true> {
326  template <class Container, typename key_type>
327  static bool run(Container &container, key_type const &key) {
328  return std::find(container.begin(), container.end(), key) !=
329  container.end();
330  }
331 };
332 
333 template <typename T>
334 struct contains_algo<T, false> {
335  template <class Container, typename key_type>
336  static bool run(Container &container, key_type const &key) {
337  for (size_t k = 0; k < container.size(); ++k) {
338  if (&container[k] == &key) return true;
339  }
340  return false;
341  }
342 };
343 
344 template <class Container, bool NoProxy>
346  : public ::boost::python::vector_indexing_suite<
347  Container, NoProxy,
348  contains_vector_derived_policies<Container, NoProxy> > {
349  typedef typename Container::value_type key_type;
350 
351  static bool contains(Container &container, key_type const &key) {
352  return contains_algo<key_type>::run(container, key);
353  }
354 };
355 } // namespace internal
356 
358  : public ::boost::python::def_visitor<EmptyPythonVisitor> {
359  template <class classT>
360  void visit(classT &) const {}
361 };
362 
374 template <class vector_type, bool NoProxy = false,
375  bool EnableFromPythonListConverter = true>
377  : public ::boost::python::vector_indexing_suite<
378  vector_type, NoProxy,
379  internal::contains_vector_derived_policies<vector_type, NoProxy> >,
380  public StdContainerFromPythonList<vector_type, NoProxy> {
381  typedef typename vector_type::value_type value_type;
382  typedef typename vector_type::allocator_type allocator_type;
385 
386  static void expose(const std::string &class_name,
387  const std::string &doc_string = "") {
388  expose(class_name, doc_string, EmptyPythonVisitor());
389  }
390 
391  template <typename VisitorDerived>
392  static void expose(
393  const std::string &class_name,
394  const boost::python::def_visitor<VisitorDerived> &visitor) {
395  expose(class_name, "", visitor);
396  }
397 
398  template <typename VisitorDerived>
399  static void expose(
400  const std::string &class_name, const std::string &doc_string,
401  const boost::python::def_visitor<VisitorDerived> &visitor) {
402  if (!register_symbolic_link_to_registered_type<vector_type>()) {
403  bp::class_<vector_type> cl(class_name.c_str(), doc_string.c_str());
404  cl.def(StdVectorPythonVisitor())
405 
406  .def(bp::init<size_t, const value_type &>(
407  bp::args("self", "size", "value"),
408  "Constructor from a given size and a given value."))
409  .def(bp::init<const vector_type &>(bp::args("self", "other"),
410  "Copy constructor"))
411 
412  .def("tolist", &FromPythonListConverter::tolist, bp::arg("self"),
413  "Returns the std::vector as a Python list.")
414  .def(visitor)
415  .def("reserve", &vector_type::reserve,
416  (bp::arg("self"), bp::arg("new_cap")),
417  "Increase the capacity of the vector to a value that's greater "
418  "or equal to new_cap.")
419  .def_pickle(PickleVector<vector_type>())
421 
422  // Register conversion
423  if (EnableFromPythonListConverter)
424  FromPythonListConverter::register_converter();
425  }
426  }
427 };
428 
432 void EIGENPY_DLLAPI exposeStdVector();
433 
434 template <typename MatType>
436  typedef std::vector<MatType, Eigen::aligned_allocator<MatType> > VecMatType;
437  std::string full_name = "StdVec_";
438  full_name += name;
440  full_name.c_str(),
442 }
443 
444 } // namespace eigenpy
445 
446 #endif // ifndef __eigenpy_utils_std_vector_hpp__
Eigen::Matrix< Scalar, Rows, Cols, Options, MaxRows, MaxCols > MatrixType
Definition: std-vector.hpp:151
::boost::python::list run(vector_type &vec)
Definition: std-vector.hpp:53
converter::extract_rvalue< RefType > base
Definition: std-vector.hpp:132
static void expose(const std::string &class_name, const std::string &doc_string, const boost::python::def_visitor< VisitorDerived > &visitor)
Definition: std-vector.hpp:399
static bool run(Container &container, key_type const &key)
Definition: std-vector.hpp:336
vector_type::allocator_type allocator_type
Definition: std-vector.hpp:382
::boost::python::list run(vector_type &vec)
Definition: std-vector.hpp:64
Definition: complex.cpp:7
StdContainerFromPythonList< vector_type, NoProxy > FromPythonListConverter
Definition: std-vector.hpp:384
extract_to_eigen_ref(api::object const &o)
Definition: std-vector.hpp:140
Create a pickle interface for the std::vector.
vector_type::allocator_type Allocator
Definition: std-vector.hpp:245
void exposeStdVectorEigenSpecificType(const char *name)
Definition: std-vector.hpp:435
static boost::python::object base_get_item(boost::python::back_reference< Container &> container, PyObject *i_)
Definition: std-vector.hpp:87
Change the behaviour of indexing (method getitem in Python). This is suitable for container of Eigen ...
Definition: std-vector.hpp:74
bool from_python_list(PyObject *obj_ptr, T *)
Check if a PyObject can be converted to an std::vector<T>.
Definition: std-vector.hpp:33
vector_type::value_type value_type
Definition: std-vector.hpp:381
static bool contains(Container &container, key_type const &key)
Definition: std-vector.hpp:351
void visit(classT &) const
Definition: std-vector.hpp:360
static void expose(const std::string &class_name, const boost::python::def_visitor< VisitorDerived > &visitor)
Definition: std-vector.hpp:392
static bool run(Container &container, key_type const &key)
Definition: std-vector.hpp:327
Register the conversion from a Python list to a std::vector.
Definition: std-vector.hpp:27
static void expose(const std::string &class_name, const std::string &doc_string="")
Definition: std-vector.hpp:386
void expose()
Call the expose function of a given type T.
Definition: expose.hpp:23
void EIGENPY_DLLAPI exposeStdVector()
Definition: std-vector.cpp:10
Eigen::TensorRef< Tensor > ref(Eigen::TensorRef< Tensor > tensor)
Definition: tensor.cpp:55
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *memory)
Allocate the std::vector and fill it with the element contained in the list.
Definition: std-vector.hpp:270
Expose an std::vector from a type given as template argument.
Definition: std-vector.hpp:376
Eigen::Ref< MatrixType > RefType
Definition: std-vector.hpp:129
static index_type convert_index(Container &container, PyObject *i_)
Definition: std-vector.hpp:103
static void * convertible(PyObject *obj_ptr)
Check if obj_ptr can be converted.
Definition: std-vector.hpp:248
Add the Python method copy to allow a copy of this by calling the copy constructor.
Definition: copyable.hpp:17
::boost::python::list tolist(vector_type &self)
Definition: std-vector.hpp:297
Definition: python.py:1


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Fri Jun 2 2023 02:10:26