.. _program_listing_file_include_eigenpy_map.hpp: Program Listing for File map.hpp ================================ |exhale_lsh| :ref:`Return to documentation for file ` (``include/eigenpy/map.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef __eigenpy_map_hpp__ #define __eigenpy_map_hpp__ #include "eigenpy/pickle-vector.hpp" #include "eigenpy/registration.hpp" #include "eigenpy/utils/empty-visitor.hpp" #include #include #include namespace eigenpy { template struct overload_base_get_item_for_map : public boost::python::def_visitor< overload_base_get_item_for_map> { typedef typename Container::value_type value_type; typedef typename Container::value_type::second_type data_type; typedef typename Container::key_type key_type; typedef typename Container::key_type 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().find(idx); if (i == container.get().end()) { PyErr_SetString(PyExc_KeyError, "Invalid key"); boost::python::throw_error_already_set(); } typename boost::python::to_python_indirect< data_type&, boost::python::detail::make_reference_holder> convert; return boost::python::object(boost::python::handle<>(convert(i->second))); } static index_type convert_index(Container& /*container*/, PyObject* i_) { boost::python::extract i(i_); if (i.check()) { return i(); } else { boost::python::extract i(i_); if (i.check()) return i(); } PyErr_SetString(PyExc_TypeError, "Invalid index type"); boost::python::throw_error_already_set(); return index_type(); } }; // The following snippet of code has been taken from the header // https://github.com/loco-3d/crocoddyl/blob/v2.1.0/bindings/python/crocoddyl/utils/map-converter.hpp // The Crocoddyl library is written by Carlos Mastalli, Nicolas Mansard and // Rohan Budhiraja. namespace bp = boost::python; template struct PickleMap : public PickleVector { static void setstate(bp::object op, bp::tuple tup) { Container& o = bp::extract(op)(); bp::stl_input_iterator begin(tup[0]), end; o.insert(begin, end); } }; template struct dict_to_map { static void register_converter() { bp::converter::registry::push_back(&dict_to_map::convertible, &dict_to_map::construct, bp::type_id()); } static void* convertible(PyObject* object) { // Check if it is a list if (!PyObject_GetIter(object)) return 0; return object; } static void construct(PyObject* object, bp::converter::rvalue_from_python_stage1_data* data) { // convert the PyObject pointed to by `object` to a bp::dict bp::handle<> handle(bp::borrowed(object)); // "smart ptr" bp::dict dict(handle); // get a pointer to memory into which we construct the map // this is provided by the Python runtime typedef bp::converter::rvalue_from_python_storage storage_type; void* storage = reinterpret_cast(data)->storage.bytes; // placement-new allocate the result new (storage) Container(); // iterate over the dictionary `dict`, fill up the map `map` Container& map(*(static_cast(storage))); bp::list keys(dict.keys()); int keycount(static_cast(bp::len(keys))); for (int i = 0; i < keycount; ++i) { // get the key bp::object keyobj(keys[i]); bp::extract keyproxy(keyobj); if (!keyproxy.check()) { PyErr_SetString(PyExc_KeyError, "Bad key type"); bp::throw_error_already_set(); } typename Container::key_type key = keyproxy(); // get the corresponding value bp::object valobj(dict[keyobj]); bp::extract valproxy(valobj); if (!valproxy.check()) { PyErr_SetString(PyExc_ValueError, "Bad value type"); bp::throw_error_already_set(); } typename Container::mapped_type val = valproxy(); map.emplace(key, val); } // remember the location for later data->convertible = storage; } static bp::dict todict(Container& self) { bp::dict dict; typename Container::const_iterator it; for (it = self.begin(); it != self.end(); ++it) { dict.setdefault(it->first, it->second); } return dict; } }; template struct emplace_set_derived_policies : bp::map_indexing_suite> { typedef typename Container::key_type index_type; typedef typename Container::value_type::second_type data_type; typedef typename Container::value_type value_type; using DerivedPolicies = bp::detail::final_map_derived_policies; template static void extension_def(Class& cl) { // Wrap the map's element (value_type) std::string elem_name = "map_indexing_suite_"; bp::object class_name(cl.attr("__name__")); bp::extract class_name_extractor(class_name); elem_name += class_name_extractor(); elem_name += "_entry"; namespace mpl = boost::mpl; typedef typename mpl::if_< mpl::and_, mpl::bool_>, bp::return_internal_reference<>, bp::default_call_policies>::type get_data_return_policy; bp::class_(elem_name.c_str(), bp::no_init) .def("__repr__", &DerivedPolicies::print_elem) .def("data", &DerivedPolicies::get_data, get_data_return_policy()) .def("key", &DerivedPolicies::get_key); } static void set_item(Container& container, index_type i, data_type const& v) { container.emplace(i, v); } }; template struct GenericMapVisitor : public emplace_set_derived_policies, public dict_to_map { typedef dict_to_map FromPythonDictConverter; template static void expose(const std::string& class_name, const std::string& doc_string, const bp::def_visitor& visitor) { namespace bp = bp; if (!register_symbolic_link_to_registered_type()) { bp::class_(class_name.c_str(), doc_string.c_str()) .def(GenericMapVisitor()) .def("todict", &FromPythonDictConverter::todict, bp::arg("self"), "Returns the map type as a Python dictionary.") .def_pickle(PickleMap()) .def(visitor); // Register conversion FromPythonDictConverter::register_converter(); } } 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); } }; } // namespace eigenpy #endif // ifndef __eigenpy_map_hpp__