7 #ifndef __eigenpy_utils_std_vector_hpp__
8 #define __eigenpy_utils_std_vector_hpp__
10 #include <boost/mpl/if.hpp>
11 #include <boost/python.hpp>
12 #include <boost/python/stl_iterator.hpp>
13 #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
19 #include "eigenpy/config.hpp"
28 template <
typename vector_type,
bool NoProxy = false>
37 if (!PyList_Check(obj_ptr))
return false;
40 bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
41 bp::list bp_list(bp_obj);
42 bp::ssize_t list_size = bp::len(bp_list);
45 for (bp::ssize_t k = 0; k < list_size; ++k) {
46 bp::extract<T> elt(bp_list[k]);
47 if (!elt.check())
return false;
53 template <
typename vector_type,
bool NoProxy>
55 static ::boost::python::list
run(vector_type &
vec,
const bool deep_copy) {
59 for (
size_t k = 0; k <
vec.size(); ++k) {
66 template <
typename vector_type>
68 static ::boost::python::list
run(vector_type &
vec,
const bool) {
69 typedef bp::iterator<vector_type> iterator;
70 return bp::list(iterator()(
vec));
77 template <
typename Container>
79 :
public boost::python::def_visitor<
80 overload_base_get_item_for_std_vector<Container> > {
85 template <
class Class>
92 boost::python::back_reference<Container &> container, PyObject *i_) {
94 typename Container::iterator i = container.get().begin();
96 if (i == container.get().end()) {
97 PyErr_SetString(PyExc_KeyError,
"Invalid index");
98 bp::throw_error_already_set();
101 typename bp::to_python_indirect<
data_type &,
102 bp::detail::make_reference_holder>
104 return bp::object(bp::handle<>(convert(*i)));
108 bp::extract<long> i(i_);
111 if (index < 0) index += (long)container.size();
112 if (index >=
long(container.size()) || index < 0) {
113 PyErr_SetString(PyExc_IndexError,
"Index out of range");
114 bp::throw_error_already_set();
119 PyErr_SetString(PyExc_TypeError,
"Invalid index type");
120 bp::throw_error_already_set();
130 template <
typename MatrixType>
132 : converter::extract_rvalue<Eigen::Ref<MatrixType> > {
136 typedef converter::extract_rvalue<RefType>
base;
149 template <
typename Scalar,
int Rows,
int Cols,
int Options,
int MaxRows,
151 struct extract<
Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> &>
153 Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols> > {
154 typedef Eigen::Matrix<Scalar, Rows, Cols, Options, MaxRows, MaxCols>
161 template <
typename Derived>
162 struct extract<
Eigen::MatrixBase<Derived> &>
170 template <
typename Derived>
171 struct extract<
Eigen::RefBase<Derived> &>
179 namespace converter {
181 template <
typename Type,
class Allocator>
182 struct reference_arg_from_python<std::vector<Type, Allocator> &>
183 : arg_lvalue_from_python_base {
190 : arg_lvalue_from_python_base(converter::get_lvalue_from_python(
200 bool is_convertible =
202 if (!is_convertible)
return;
204 typedef ::eigenpy::StdContainerFromPythonList<vector_type> Constructor;
205 Constructor::construct(py_obj, &m_data.stage1);
207 void *&m_result =
const_cast<void *&
>(result());
208 m_result = m_data.stage1.convertible;
209 vec_ptr =
reinterpret_cast<vector_type *
>(m_data.storage.bytes);
213 return ::boost::python::detail::void_ptr_to_reference(result(),
218 if (m_data.stage1.convertible == m_data.storage.bytes) {
221 list bp_list(handle<>(borrowed(m_source)));
222 for (
size_t i = 0; i <
vec.size(); ++i) {
223 typename extract_type::result_type elt =
extract_type(bp_list[i]);
230 rvalue_from_python_data<ref_vector_type>
m_data;
243 template <
class Container>
249 template <
typename _Tp, std::
size_t Size>
260 template <
typename vector_type,
bool NoProxy>
262 typedef typename vector_type::value_type
T;
270 if (!PyList_Check(obj_ptr))
return 0;
273 bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
274 bp::list bp_list(bp_obj);
275 bp::ssize_t list_size = bp::len(bp_list);
278 for (bp::ssize_t k = 0; k < list_size; ++k) {
279 bp::extract<T> elt(bp_list[k]);
280 if (!elt.check())
return 0;
290 boost::python::converter::rvalue_from_python_stage1_data *memory) {
292 bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
293 bp::list bp_list(bp_obj);
297 bp::converter::rvalue_from_python_storage<vector_type> *
>(
298 reinterpret_cast<void *
>(memory))
301 typedef bp::stl_input_iterator<T> iterator;
304 new (storage) vector_type(iterator(bp_list), iterator());
307 memory->convertible = storage;
311 ::boost::python::converter::registry::push_back(
315 static ::boost::python::list
tolist(vector_type &
self,
316 const bool deep_copy =
false) {
323 template <
typename T,
324 bool has_operator_equal_value =
325 std::is_base_of<std::true_type, has_operator_equal<T> >
::value>
328 template <
typename T>
330 template <
class Container,
typename key_type>
331 static bool run(
const Container &container, key_type
const &key) {
332 return std::find(container.begin(), container.end(), key) !=
337 template <
typename T>
339 template <
class Container,
typename key_type>
340 static bool run(
const Container &container, key_type
const &key) {
341 for (
size_t k = 0; k < container.size(); ++k) {
342 if (&container[k] == &key)
return true;
348 template <
class Container,
bool NoProxy>
350 :
public ::boost::python::vector_indexing_suite<
352 contains_vector_derived_policies<Container, NoProxy> > {
365 template <
typename Container,
bool NoProxy,
typename CoVisitor>
367 :
public boost::python::def_visitor<
368 ExposeStdMethodToStdVector<Container, NoProxy, CoVisitor> > {
375 template <
class Class>
379 (bp::arg(
"self"), bp::arg(
"deep_copy") =
false),
380 "Returns the std::vector as a Python list.")
381 .def(
"reserve", &Container::reserve,
382 (bp::arg(
"self"), bp::arg(
"new_cap")),
383 "Increase the capacity of the vector to a value that's greater "
384 "or equal to new_cap.")
392 template <
typename Container,
bool NoProxy,
typename CoVisitor>
401 template <
typename vector_type,
bool T_picklable = false>
403 static void run(bp::class_<vector_type> &) {}
406 template <
typename vector_type>
408 static void run(bp::class_<vector_type> &cl) {
422 template <
class vector_type,
bool NoProxy =
false,
423 bool EnableFromPythonListConverter =
true,
bool pickable =
true>
429 static void expose(
const std::string &class_name,
430 const std::string &doc_string =
"") {
434 template <
typename DerivedVisitor>
435 static void expose(
const std::string &class_name,
436 const bp::def_visitor<DerivedVisitor> &visitor) {
437 expose(class_name,
"", visitor);
440 template <
typename DerivedVisitor>
441 static void expose(
const std::string &class_name,
442 const std::string &doc_string,
443 const bp::def_visitor<DerivedVisitor> &visitor) {
446 auto add_std_visitor =
447 internal::createExposeStdMethodToStdVector<vector_type, NoProxy>(
449 if (!register_symbolic_link_to_registered_type<vector_type>(
451 bp::class_<vector_type> cl(class_name.c_str(), doc_string.c_str());
455 boost::python::vector_indexing_suite<
456 vector_type, NoProxy,
460 cl.def(bp::init<size_t, const value_type &>(
461 bp::args(
"self",
"size",
"value"),
462 "Constructor from a given size and a given value."))
463 .def(bp::init<const vector_type &>(bp::args(
"self",
"other"),
466 .def(vector_indexing)
467 .def(add_std_visitor);
471 if (EnableFromPythonListConverter) {
483 template <
typename MatType,
typename Alloc = Eigen::aligned_allocator<MatType> >
485 typedef std::vector<MatType, Alloc> VecMatType;
486 std::string full_name =
"StdVec_";
495 #endif // ifndef __eigenpy_utils_std_vector_hpp__