.. _program_listing_file__tmp_ws_src_eigenpy_include_eigenpy_std-vector.hpp: Program Listing for File std-vector.hpp ======================================= |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/eigenpy/include/eigenpy/std-vector.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef __eigenpy_utils_std_vector_hpp__ #define __eigenpy_utils_std_vector_hpp__ #include #include #include #include #include #include #include #include "eigenpy/eigenpy.hpp" #include "eigenpy/config.hpp" #include "eigenpy/copyable.hpp" #include "eigenpy/eigen-to-python.hpp" #include "eigenpy/pickle-vector.hpp" #include "eigenpy/registration.hpp" namespace eigenpy { // Forward declaration template struct StdContainerFromPythonList; namespace details { template bool from_python_list(PyObject *obj_ptr, T *) { // Check if it is a list if (!PyList_Check(obj_ptr)) return false; // Retrieve the underlying list bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr))); bp::list bp_list(bp_obj); bp::ssize_t list_size = bp::len(bp_list); // Check if all the elements contained in the current vector is of type T for (bp::ssize_t k = 0; k < list_size; ++k) { bp::extract elt(bp_list[k]); if (!elt.check()) return false; } return true; } template struct build_list { static ::boost::python::list run(vector_type &vec, const bool deep_copy) { if (deep_copy) return build_list::run(vec, true); bp::list bp_list; for (size_t k = 0; k < vec.size(); ++k) { bp_list.append(boost::ref(vec[k])); } return bp_list; } }; template struct build_list { static ::boost::python::list run(vector_type &vec, const bool) { typedef bp::iterator iterator; return bp::list(iterator()(vec)); } }; template struct overload_base_get_item_for_std_vector : public boost::python::def_visitor< overload_base_get_item_for_std_vector > { typedef typename Container::value_type value_type; typedef typename Container::value_type data_type; typedef size_t index_type; template void visit(Class &cl) const { cl.def("__getitem__", &base_get_item); } private: static boost::python::object base_get_item( boost::python::back_reference container, PyObject *i_) { index_type idx = convert_index(container.get(), i_); typename Container::iterator i = container.get().begin(); std::advance(i, idx); if (i == container.get().end()) { PyErr_SetString(PyExc_KeyError, "Invalid index"); bp::throw_error_already_set(); } typename bp::to_python_indirect convert; return bp::object(bp::handle<>(convert(*i))); } static index_type convert_index(Container &container, PyObject *i_) { bp::extract i(i_); if (i.check()) { long index = i(); if (index < 0) index += (long)container.size(); if (index >= long(container.size()) || index < 0) { PyErr_SetString(PyExc_IndexError, "Index out of range"); bp::throw_error_already_set(); } return (index_type)index; } PyErr_SetString(PyExc_TypeError, "Invalid index type"); bp::throw_error_already_set(); return index_type(); } }; } // namespace details } // namespace eigenpy namespace boost { namespace python { template struct extract_to_eigen_ref : converter::extract_rvalue > { typedef Eigen::Ref RefType; protected: typedef converter::extract_rvalue base; public: typedef RefType result_type; operator result_type() const { return (*this)(); } extract_to_eigen_ref(PyObject *o) : base(o) {} extract_to_eigen_ref(api::object const &o) : base(o.ptr()) {} }; template struct extract &> : extract_to_eigen_ref< Eigen::Matrix > { typedef Eigen::Matrix MatrixType; typedef extract_to_eigen_ref base; extract(PyObject *o) : base(o) {} extract(api::object const &o) : base(o.ptr()) {} }; template struct extract &> : extract_to_eigen_ref > { typedef Eigen::MatrixBase MatrixType; typedef extract_to_eigen_ref base; extract(PyObject *o) : base(o) {} extract(api::object const &o) : base(o.ptr()) {} }; template struct extract &> : extract_to_eigen_ref > { typedef Eigen::RefBase MatrixType; typedef extract_to_eigen_ref base; extract(PyObject *o) : base(o) {} extract(api::object const &o) : base(o.ptr()) {} }; namespace converter { template struct reference_arg_from_python &> : arg_lvalue_from_python_base { typedef std::vector vector_type; typedef vector_type &ref_vector_type; typedef ref_vector_type result_type; typedef extract extract_type; reference_arg_from_python(PyObject *py_obj) : arg_lvalue_from_python_base(converter::get_lvalue_from_python( py_obj, registered::converters)), m_data(NULL), m_source(py_obj), vec_ptr(NULL) { if (result() != 0) // we have found a lvalue converter return; // Check if py_obj is a py_list, which can then be converted to an // std::vector bool is_convertible = ::eigenpy::details::from_python_list(py_obj, (Type *)(0)); if (!is_convertible) return; typedef ::eigenpy::StdContainerFromPythonList Constructor; Constructor::construct(py_obj, &m_data.stage1); void *&m_result = const_cast(result()); m_result = m_data.stage1.convertible; vec_ptr = reinterpret_cast(m_data.storage.bytes); } result_type operator()() const { return ::boost::python::detail::void_ptr_to_reference(result(), (result_type(*)())0); } ~reference_arg_from_python() { if (m_data.stage1.convertible == m_data.storage.bytes) { // Copy back the reference const vector_type &vec = *vec_ptr; list bp_list(handle<>(borrowed(m_source))); for (size_t i = 0; i < vec.size(); ++i) { typename extract_type::result_type elt = extract_type(bp_list[i]); elt = vec[i]; } } } private: rvalue_from_python_data m_data; PyObject *m_source; vector_type *vec_ptr; }; } // namespace converter } // namespace python } // namespace boost namespace eigenpy { namespace details { template struct container_traits { // default behavior expects allocators typedef typename Container::allocator_type Allocator; }; template struct container_traits > { typedef void Allocator; }; }; // namespace details template struct StdContainerFromPythonList { typedef typename vector_type::value_type T; typedef typename details::container_traits::Allocator Allocator; static void *convertible(PyObject *obj_ptr) { namespace bp = boost::python; // Check if it is a list if (!PyList_Check(obj_ptr)) return 0; // Retrieve the underlying list bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr))); bp::list bp_list(bp_obj); bp::ssize_t list_size = bp::len(bp_list); // Check if all the elements contained in the current vector is of type T for (bp::ssize_t k = 0; k < list_size; ++k) { bp::extract elt(bp_list[k]); if (!elt.check()) return 0; } return obj_ptr; } static void construct( PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *memory) { // Extract the list bp::object bp_obj(bp::handle<>(bp::borrowed(obj_ptr))); bp::list bp_list(bp_obj); void *storage = reinterpret_cast< bp::converter::rvalue_from_python_storage *>( reinterpret_cast(memory)) ->storage.bytes; typedef bp::stl_input_iterator iterator; // Build the std::vector new (storage) vector_type(iterator(bp_list), iterator()); // Validate the construction memory->convertible = storage; } static void register_converter() { ::boost::python::converter::registry::push_back( &convertible, &construct, ::boost::python::type_id()); } static ::boost::python::list tolist(vector_type &self, const bool deep_copy = false) { return details::build_list::run(self, deep_copy); } }; namespace internal { template >::value> struct contains_algo; template struct contains_algo { template static bool run(const Container &container, key_type const &key) { return std::find(container.begin(), container.end(), key) != container.end(); } }; template struct contains_algo { template static bool run(const Container &container, key_type const &key) { for (size_t k = 0; k < container.size(); ++k) { if (&container[k] == &key) return true; } return false; } }; template struct contains_vector_derived_policies : public ::boost::python::vector_indexing_suite< Container, NoProxy, contains_vector_derived_policies > { typedef typename Container::value_type key_type; static bool contains(Container &container, key_type const &key) { return contains_algo::run(container, key); } }; template struct ExposeStdMethodToStdVector : public boost::python::def_visitor< ExposeStdMethodToStdVector > { typedef StdContainerFromPythonList FromPythonListConverter; ExposeStdMethodToStdVector(const CoVisitor &co_visitor) : m_co_visitor(co_visitor) {} template void visit(Class &cl) const { cl.def(m_co_visitor) .def("tolist", &FromPythonListConverter::tolist, (bp::arg("self"), bp::arg("deep_copy") = false), "Returns the std::vector as a Python list.") .def("reserve", &Container::reserve, (bp::arg("self"), bp::arg("new_cap")), "Increase the capacity of the vector to a value that's greater " "or equal to new_cap.") .def(CopyableVisitor()); } const CoVisitor &m_co_visitor; }; template static ExposeStdMethodToStdVector createExposeStdMethodToStdVector(const CoVisitor &co_visitor) { return ExposeStdMethodToStdVector(co_visitor); } } // namespace internal struct EmptyPythonVisitor : public ::boost::python::def_visitor { template void visit(classT &) const {} }; namespace internal { template struct def_pickle_std_vector { static void run(bp::class_ &) {} }; template struct def_pickle_std_vector { static void run(bp::class_ &cl) { cl.def_pickle(PickleVector()); } }; } // namespace internal template struct StdVectorPythonVisitor { typedef typename vector_type::value_type value_type; typedef StdContainerFromPythonList FromPythonListConverter; static void expose(const std::string &class_name, const std::string &doc_string = "") { expose(class_name, doc_string, EmptyPythonVisitor()); } template static void expose(const std::string &class_name, const bp::def_visitor &visitor) { expose(class_name, "", visitor); } template static void expose(const std::string &class_name, const std::string &doc_string, const bp::def_visitor &visitor) { // Apply visitor on already registered type or if type is not already // registered, we define and apply the visitor on it auto add_std_visitor = internal::createExposeStdMethodToStdVector( visitor); if (!register_symbolic_link_to_registered_type( add_std_visitor)) { bp::class_ cl(class_name.c_str(), doc_string.c_str()); // Standard vector indexing definition boost::python::vector_indexing_suite< vector_type, NoProxy, internal::contains_vector_derived_policies > vector_indexing; cl.def(bp::init( bp::args("self", "size", "value"), "Constructor from a given size and a given value.")) .def(bp::init(bp::args("self", "other"), "Copy constructor")) .def(vector_indexing) .def(add_std_visitor); internal::def_pickle_std_vector::run(cl); } if (EnableFromPythonListConverter) { // Register conversion FromPythonListConverter::register_converter(); } } }; void EIGENPY_DLLAPI exposeStdVector(); template void exposeStdVectorEigenSpecificType(const char *name) { typedef std::vector > VecMatType; std::string full_name = "StdVec_"; full_name += name; StdVectorPythonVisitor::expose( full_name.c_str(), details::overload_base_get_item_for_std_vector()); } } // namespace eigenpy #endif // ifndef __eigenpy_utils_std_vector_hpp__