6 #ifndef __eigenpy_utils_std_vector_hpp__ 7 #define __eigenpy_utils_std_vector_hpp__ 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> 18 #include "eigenpy/config.hpp" 26 template <
typename vector_type,
bool NoProxy = false>
35 if (!PyList_Check(obj_ptr))
return false;
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);
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;
51 template <
typename vector_type,
bool NoProxy>
53 static ::boost::python::list
run(vector_type &
vec) {
55 for (
size_t k = 0; k < vec.size(); ++k) {
62 template <
typename vector_type>
64 static ::boost::python::list
run(vector_type &
vec) {
65 typedef bp::iterator<vector_type> iterator;
66 return bp::list(iterator()(vec));
73 template <
typename Container>
75 :
public boost::python::def_visitor<
76 overload_base_get_item_for_std_vector<Container> > {
81 template <
class Class>
83 cl.def(
"__getitem__", &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();
92 if (i == container.get().end()) {
93 PyErr_SetString(PyExc_KeyError,
"Invalid index");
94 bp::throw_error_already_set();
97 typename bp::to_python_indirect<data_type &,
98 bp::detail::make_reference_holder>
100 return bp::object(bp::handle<>(convert(*i)));
104 bp::extract<long> i(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();
112 return (index_type)index;
115 PyErr_SetString(PyExc_TypeError,
"Invalid index type");
116 bp::throw_error_already_set();
126 template <
typename MatrixType>
128 : converter::extract_rvalue<Eigen::Ref<MatrixType> > {
132 typedef converter::extract_rvalue<RefType>
base;
137 operator result_type()
const {
return (*
this)(); }
145 template <
typename Scalar,
int Rows,
int Cols,
int Options,
int MaxRows,
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>
154 extract(api::object
const &o) : base(o.ptr()) {}
157 template <
typename Derived>
158 struct extract<
Eigen::MatrixBase<Derived> &>
163 extract(api::object
const &o) : base(o.ptr()) {}
166 template <
typename Derived>
167 struct extract<
Eigen::RefBase<Derived> &>
172 extract(api::object
const &o) : base(o.ptr()) {}
175 namespace converter {
177 template <
typename Type,
class Allocator>
178 struct reference_arg_from_python<std::vector<Type, Allocator> &>
179 : arg_lvalue_from_python_base {
186 : arg_lvalue_from_python_base(converter::get_lvalue_from_python(
187 py_obj, registered<vector_type>::converters)),
196 bool is_convertible =
198 if (!is_convertible)
return;
200 typedef ::eigenpy::StdContainerFromPythonList<vector_type> Constructor;
201 Constructor::construct(py_obj, &m_data.stage1);
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);
209 return ::boost::python::detail::void_ptr_to_reference(result(),
210 (result_type(*)())0);
214 if (m_data.stage1.convertible == m_data.storage.bytes) {
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]);
226 rvalue_from_python_data<ref_vector_type>
m_data;
242 template <
typename vector_type,
bool NoProxy>
243 struct StdContainerFromPythonList {
244 typedef typename vector_type::value_type
T;
252 if (!PyList_Check(obj_ptr))
return 0;
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);
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;
272 boost::python::converter::rvalue_from_python_stage1_data *memory) {
274 bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr)));
275 bp::list bp_list(bp_obj);
279 bp::converter::rvalue_from_python_storage<vector_type> *
>(
280 reinterpret_cast<void *
>(memory))
283 typedef bp::stl_input_iterator<T> iterator;
286 new (storage) vector_type(iterator(bp_list), iterator());
289 memory->convertible = storage;
293 ::boost::python::converter::registry::push_back(
294 &convertible, &construct, ::boost::python::type_id<vector_type>());
297 static ::boost::python::list
tolist(vector_type &
self) {
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 {};
310 template <
typename T,
class A>
316 template <
typename EigenObject>
320 template <
typename T,
bool has_operator_equal_value = boost::is_base_of<
324 template <
typename T>
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) !=
333 template <
typename T>
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;
344 template <
class Container,
bool NoProxy>
346 :
public ::boost::python::vector_indexing_suite<
348 contains_vector_derived_policies<Container, NoProxy> > {
351 static bool contains(Container &container, key_type
const &key) {
358 :
public ::boost::python::def_visitor<EmptyPythonVisitor> {
359 template <
class classT>
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> >,
386 static void expose(
const std::string &class_name,
387 const std::string &doc_string =
"") {
391 template <
typename VisitorDerived>
393 const std::string &class_name,
394 const boost::python::def_visitor<VisitorDerived> &visitor) {
395 expose(class_name,
"", visitor);
398 template <
typename VisitorDerived>
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());
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"),
412 .def(
"tolist", &FromPythonListConverter::tolist, bp::arg(
"self"),
413 "Returns the std::vector as a Python list.")
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.")
423 if (EnableFromPythonListConverter)
424 FromPythonListConverter::register_converter();
434 template <
typename MatType>
436 typedef std::vector<MatType, Eigen::aligned_allocator<MatType> > VecMatType;
437 std::string full_name =
"StdVec_";
446 #endif // ifndef __eigenpy_utils_std_vector_hpp__
::boost::python::list run(vector_type &vec)
std::vector< Type, Allocator > vector_type
static void expose(const std::string &class_name, const std::string &doc_string, const boost::python::def_visitor< VisitorDerived > &visitor)
static bool run(Container &container, key_type const &key)
Container::value_type key_type
vector_type::allocator_type allocator_type
result_type operator()() const
::boost::python::list run(vector_type &vec)
Container::value_type data_type
StdContainerFromPythonList< vector_type, NoProxy > FromPythonListConverter
Create a pickle interface for the std::vector.
vector_type::allocator_type Allocator
Container::value_type value_type
void exposeStdVectorEigenSpecificType(const char *name)
static boost::python::object base_get_item(boost::python::back_reference< Container &> container, PyObject *i_)
Change the behaviour of indexing (method getitem in Python). This is suitable for container of Eigen ...
bool from_python_list(PyObject *obj_ptr, T *)
Check if a PyObject can be converted to an std::vector<T>.
vector_type::value_type value_type
static bool contains(Container &container, key_type const &key)
reference_arg_from_python(PyObject *py_obj)
void visit(Class &cl) const
vector_type::value_type T
void visit(classT &) const
static void expose(const std::string &class_name, const boost::python::def_visitor< VisitorDerived > &visitor)
static bool run(Container &container, key_type const &key)
vector_type & ref_vector_type
~reference_arg_from_python()
Register the conversion from a Python list to a std::vector.
ref_vector_type result_type
static void expose(const std::string &class_name, const std::string &doc_string="")
void expose()
Call the expose function of a given type T.
void EIGENPY_DLLAPI exposeStdVector()
Eigen::TensorRef< Tensor > ref(Eigen::TensorRef< Tensor > tensor)
rvalue_from_python_data< ref_vector_type > m_data
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.
Expose an std::vector from a type given as template argument.
static void register_converter()
static index_type convert_index(Container &container, PyObject *i_)
static void * convertible(PyObject *obj_ptr)
Check if obj_ptr can be converted.
extract< Type & > extract_type
Add the Python method copy to allow a copy of this by calling the copy constructor.
::boost::python::list tolist(vector_type &self)