map.hpp
Go to the documentation of this file.
1 
6 #ifndef __eigenpy_map_hpp__
7 #define __eigenpy_map_hpp__
8 
10 #include "eigenpy/registration.hpp"
12 
13 #include <boost/python/suite/indexing/map_indexing_suite.hpp>
14 #include <boost/python/stl_iterator.hpp>
15 #include <boost/python/to_python_converter.hpp>
16 
17 namespace eigenpy {
18 
23 template <typename Container>
25  : public boost::python::def_visitor<
26  overload_base_get_item_for_map<Container> > {
27  typedef typename Container::value_type value_type;
28  typedef typename Container::value_type::second_type data_type;
29  typedef typename Container::key_type key_type;
30  typedef typename Container::key_type index_type;
31 
32  template <class Class>
33  void visit(Class& cl) const {
34  cl.def("__getitem__", &base_get_item);
35  }
36 
37  private:
38  static boost::python::object base_get_item(
39  boost::python::back_reference<Container&> container, PyObject* i_) {
40  index_type idx = convert_index(container.get(), i_);
41  typename Container::iterator i = container.get().find(idx);
42  if (i == container.get().end()) {
43  PyErr_SetString(PyExc_KeyError, "Invalid key");
44  boost::python::throw_error_already_set();
45  }
46 
47  typename boost::python::to_python_indirect<
48  data_type&, boost::python::detail::make_reference_holder>
49  convert;
50  return boost::python::object(boost::python::handle<>(convert(i->second)));
51  }
52 
53  static index_type convert_index(Container& /*container*/, PyObject* i_) {
54  boost::python::extract<key_type const&> i(i_);
55  if (i.check()) {
56  return i();
57  } else {
58  boost::python::extract<key_type> i(i_);
59  if (i.check()) return i();
60  }
61 
62  PyErr_SetString(PyExc_TypeError, "Invalid index type");
63  boost::python::throw_error_already_set();
64  return index_type();
65  }
66 };
67 
69 // The following snippet of code has been taken from the header
70 // https://github.com/loco-3d/crocoddyl/blob/v2.1.0/bindings/python/crocoddyl/utils/map-converter.hpp
71 // The Crocoddyl library is written by Carlos Mastalli, Nicolas Mansard and
72 // Rohan Budhiraja.
74 
75 namespace bp = boost::python;
76 
83 template <typename Container>
84 struct PickleMap : public PickleVector<Container> {
85  static void setstate(bp::object op, bp::tuple tup) {
86  Container& o = bp::extract<Container&>(op)();
87  bp::stl_input_iterator<typename Container::value_type> begin(tup[0]), end;
88  o.insert(begin, end);
89  }
90 };
91 
95 template <typename Container>
96 struct dict_to_map {
97  static void register_converter() {
98  bp::converter::registry::push_back(&dict_to_map::convertible,
100  bp::type_id<Container>());
101  }
102 
104  static void* convertible(PyObject* object) {
105  // Check if it is a list
106  if (!PyObject_GetIter(object)) return 0;
107  return object;
108  }
109 
111  static void construct(PyObject* object,
112  bp::converter::rvalue_from_python_stage1_data* data) {
113  // convert the PyObject pointed to by `object` to a bp::dict
114  bp::handle<> handle(bp::borrowed(object)); // "smart ptr"
115  bp::dict dict(handle);
116 
117  // get a pointer to memory into which we construct the map
118  // this is provided by the Python runtime
119  typedef bp::converter::rvalue_from_python_storage<Container> storage_type;
120  void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
121 
122  // placement-new allocate the result
123  new (storage) Container();
124 
125  // iterate over the dictionary `dict`, fill up the map `map`
126  Container& map(*(static_cast<Container*>(storage)));
127  bp::list keys(dict.keys());
128  int keycount(static_cast<int>(bp::len(keys)));
129  for (int i = 0; i < keycount; ++i) {
130  // get the key
131  bp::object keyobj(keys[i]);
132  bp::extract<typename Container::key_type> keyproxy(keyobj);
133  if (!keyproxy.check()) {
134  PyErr_SetString(PyExc_KeyError, "Bad key type");
135  bp::throw_error_already_set();
136  }
137  typename Container::key_type key = keyproxy();
138 
139  // get the corresponding value
140  bp::object valobj(dict[keyobj]);
141  bp::extract<typename Container::mapped_type> valproxy(valobj);
142  if (!valproxy.check()) {
143  PyErr_SetString(PyExc_ValueError, "Bad value type");
144  bp::throw_error_already_set();
145  }
146  typename Container::mapped_type val = valproxy();
147  map.emplace(key, val);
148  }
149 
150  // remember the location for later
151  data->convertible = storage;
152  }
153 
154  static bp::dict todict(Container& self) {
155  bp::dict dict;
156  typename Container::const_iterator it;
157  for (it = self.begin(); it != self.end(); ++it) {
158  dict.setdefault(it->first, it->second);
159  }
160  return dict;
161  }
162 };
163 
166 template <class Container, bool NoProxy>
168  : bp::map_indexing_suite<
169  Container, NoProxy,
170  emplace_set_derived_policies<Container, NoProxy> > {
171  typedef typename Container::key_type index_type;
172  typedef typename Container::value_type::second_type data_type;
173  typedef typename Container::value_type value_type;
174  using DerivedPolicies =
175  bp::detail::final_map_derived_policies<Container, NoProxy>;
176 
177  template <class Class>
178  static void extension_def(Class& cl) {
179  // Wrap the map's element (value_type)
180  std::string elem_name = "map_indexing_suite_";
181  bp::object class_name(cl.attr("__name__"));
182  bp::extract<std::string> class_name_extractor(class_name);
183  elem_name += class_name_extractor();
184  elem_name += "_entry";
185  namespace mpl = boost::mpl;
186 
187  typedef typename mpl::if_<
188  mpl::and_<boost::is_class<data_type>, mpl::bool_<!NoProxy> >,
189  bp::return_internal_reference<>, bp::default_call_policies>::type
190  get_data_return_policy;
191 
192  bp::class_<value_type>(elem_name.c_str(), bp::no_init)
193  .def("__repr__", &DerivedPolicies::print_elem)
194  .def("data", &DerivedPolicies::get_data, get_data_return_policy())
195  .def("key", &DerivedPolicies::get_key);
196  }
197 
198  static void set_item(Container& container, index_type i, data_type const& v) {
199  container.emplace(i, v);
200  }
201 };
202 
210 template <class Container, bool NoProxy = false>
212  : public emplace_set_derived_policies<Container, NoProxy>,
213  public dict_to_map<Container> {
215 
216  template <typename DerivedVisitor>
217  static void expose(const std::string& class_name,
218  const std::string& doc_string,
219  const bp::def_visitor<DerivedVisitor>& visitor) {
220  namespace bp = bp;
221 
222  if (!register_symbolic_link_to_registered_type<Container>()) {
223  bp::class_<Container>(class_name.c_str(), doc_string.c_str())
224  .def(GenericMapVisitor())
225  .def("todict", &FromPythonDictConverter::todict, bp::arg("self"),
226  "Returns the map type as a Python dictionary.")
227  .def_pickle(PickleMap<Container>())
228  .def(visitor);
229  // Register conversion
231  }
232  }
233 
234  static void expose(const std::string& class_name,
235  const std::string& doc_string = "") {
236  expose(class_name, doc_string, EmptyPythonVisitor());
237  }
238 
239  template <typename DerivedVisitor>
240  static void expose(const std::string& class_name,
241  const bp::def_visitor<DerivedVisitor>& visitor) {
242  expose(class_name, "", visitor);
243  }
244 };
245 
246 } // namespace eigenpy
247 
248 #endif // ifndef __eigenpy_map_hpp__
eigenpy::dict_to_map::todict
static bp::dict todict(Container &self)
Definition: map.hpp:154
eigenpy::overload_base_get_item_for_map::convert_index
static index_type convert_index(Container &, PyObject *i_)
Definition: map.hpp:53
boost::python
Definition: alignment.hpp:49
registration.hpp
eigenpy::emplace_set_derived_policies::set_item
static void set_item(Container &container, index_type i, data_type const &v)
Definition: map.hpp:198
eigenpy::emplace_set_derived_policies< Container, false >::DerivedPolicies
bp::detail::final_map_derived_policies< Container, NoProxy > DerivedPolicies
Definition: map.hpp:175
test_std_map.val
val
Definition: test_std_map.py:14
eigenpy::overload_base_get_item_for_map
Change the behavior of indexing (method getitem in Python). This is suitable e.g. for container of Ei...
Definition: map.hpp:24
setup.data
data
Definition: setup.in.py:48
eigenpy::PickleMap::setstate
static void setstate(bp::object op, bp::tuple tup)
Definition: map.hpp:85
eigenpy::PickleVector
Create a pickle interface for the std::vector.
Definition: pickle-vector.hpp:19
eigenpy::overload_base_get_item_for_map::key_type
Container::key_type key_type
Definition: map.hpp:29
eigenpy::emplace_set_derived_policies::value_type
Container::value_type value_type
Definition: map.hpp:173
eigenpy::GenericMapVisitor::FromPythonDictConverter
dict_to_map< Container > FromPythonDictConverter
Definition: map.hpp:214
eigenpy::emplace_set_derived_policies::data_type
Container::value_type::second_type data_type
Definition: map.hpp:172
eigenpy::GenericMapVisitor::expose
static void expose(const std::string &class_name, const std::string &doc_string="")
Definition: map.hpp:234
eigenpy::overload_base_get_item_for_map::value_type
Container::value_type value_type
Definition: map.hpp:27
eigenpy
Definition: alignment.hpp:14
eigenpy::overload_base_get_item_for_map::index_type
Container::key_type index_type
Definition: map.hpp:30
eigenpy::dict_to_map::construct
static void construct(PyObject *object, bp::converter::rvalue_from_python_stage1_data *data)
Perform the conversion.
Definition: map.hpp:111
eigenpy::overload_base_get_item_for_map::visit
void visit(Class &cl) const
Definition: map.hpp:33
eigenpy::PickleMap
Create a pickle interface for the map type.
Definition: map.hpp:84
eigenpy::EmptyPythonVisitor
Definition: empty-visitor.hpp:8
pickle-vector.hpp
eigenpy::GenericMapVisitor::expose
static void expose(const std::string &class_name, const std::string &doc_string, const bp::def_visitor< DerivedVisitor > &visitor)
Definition: map.hpp:217
eigenpy::GenericMapVisitor::expose
static void expose(const std::string &class_name, const bp::def_visitor< DerivedVisitor > &visitor)
Definition: map.hpp:240
eigenpy::dict_to_map::register_converter
static void register_converter()
Definition: map.hpp:97
eigenpy::GenericMapVisitor
Expose the map-like container, e.g. (std::map).
Definition: map.hpp:211
eigenpy::emplace_set_derived_policies::index_type
Container::key_type index_type
Definition: map.hpp:171
eigenpy::emplace_set_derived_policies
Definition: map.hpp:167
eigenpy::emplace_set_derived_policies::extension_def
static void extension_def(Class &cl)
Definition: map.hpp:178
test_geometry.v
v
Definition: test_geometry.py:32
eigenpy::overload_base_get_item_for_map::base_get_item
static boost::python::object base_get_item(boost::python::back_reference< Container & > container, PyObject *i_)
Definition: map.hpp:38
eigenpy::dict_to_map::convertible
static void * convertible(PyObject *object)
Check if conversion is possible.
Definition: map.hpp:104
eigenpy::dict_to_map
Definition: map.hpp:96
empty-visitor.hpp
eigenpy::overload_base_get_item_for_map::data_type
Container::value_type::second_type data_type
Definition: map.hpp:28


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Sat Nov 2 2024 02:14:45