knowrob  2.1.0
A Knowledge Base System for Cognition-enabled Robots
dict.h
Go to the documentation of this file.
1 
2 #ifndef KNOWROB_PY_CONVERTER_PYTHON_TO_MAP_H
3 #define KNOWROB_PY_CONVERTER_PYTHON_TO_MAP_H
4 
5 #include <boost/python.hpp>
6 #include <unordered_map>
7 #include <boost/any.hpp>
8 #include <stdexcept>
9 
10 namespace knowrob::py {
11 
12  // Function to convert Python object to boost::any
13  boost::any python_to_boost_any(const boost::python::object &obj) {
14  using namespace boost::python;
15 
16  if (extract<int>(obj).check()) {
17  return boost::any(extract<int>(obj)());
18  } else if (extract<double>(obj).check()) {
19  return boost::any(extract<double>(obj)());
20  } else if (extract<std::string>(obj).check()) {
21  return boost::any(extract<std::string>(obj)());
22  } else {
23  // Add more type checks as needed
24  PyErr_SetString(PyExc_TypeError, "Unsupported type in Python object");
25  throw_error_already_set();
26  }
27 
28  return boost::any(); // This will never be reached
29  }
30 
31  // Function to convert Python dict to std::unordered_map<std::string, boost::any>
32  std::unordered_map<std::string, boost::any> dict_to_map(const boost::python::dict &py_dict) {
33  std::unordered_map<std::string, boost::any> map;
34  boost::python::list keys = py_dict.keys();
35  for (int i = 0; i < len(keys); ++i) {
36  std::string key = boost::python::extract<std::string>(keys[i]);
37  boost::python::object value = py_dict[keys[i]];
38  map[key] = python_to_boost_any(value);
39  }
40  return map;
41  }
42 
43  // Converter from Python dict to C++ std::unordered_map<std::string, boost::any>
44  struct DictToMapConverter {
45  static void *convertible(PyObject *obj_ptr) {
46  if (!PyDict_Check(obj_ptr)) return 0;
47  return obj_ptr;
48  }
49 
50  static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data) {
51  void *storage = ((boost::python::converter::rvalue_from_python_storage<std::unordered_map<std::string, boost::any>> *) data)->storage.bytes;
52  new(storage) std::unordered_map<std::string, boost::any>(
53  dict_to_map(boost::python::dict(boost::python::borrowed(obj_ptr))));
54  data->convertible = storage;
55  }
56  };
57 
58  // Register the converter in the module initialization function
60  boost::python::converter::registry::push_back(
63  boost::python::type_id<std::unordered_map<std::string, boost::any>>());
64  }
65 
66  template<typename KeyT, typename ValT, typename Map = std::map<KeyT, ValT>>
67  struct dict_map_converter {
69  boost::python::converter::registry::push_back(
72  boost::python::type_id<Map>());
73  }
74 
76  boost::python::to_python_converter<Map, dict_map_converter<KeyT, ValT, Map>, true>();
77  }
78 
82  }
83 
84  static void *convertible(PyObject *obj) {
85  if (!PyDict_Check(obj))
86  return nullptr;
87 
88  PyObject * key, *val;
89  Py_ssize_t pos = 0;
90  while (PyDict_Next(obj, &pos, &key, &val)) {
91  boost::python::extract <KeyT> key_e(key);
92  boost::python::extract <ValT> val_e(val);
93  if (!key_e.check() || !val_e.check()) {
94  return nullptr;
95  }
96  }
97  return obj;
98  }
99 
100  static void construct(PyObject *obj,
101  boost::python::converter::rvalue_from_python_stage1_data *data) {
102  void *storage = ((boost::python::converter::rvalue_from_python_storage <Map> *) data)->storage.bytes;
103  auto pmap = new(storage) Map();
104 
105  PyObject * key, *val;
106  Py_ssize_t pos = 0;
107  while (PyDict_Next(obj, &pos, &key, &val)) {
108  (*pmap)[boost::python::extract<KeyT>(key)] = boost::python::extract<ValT>(val);
109  }
110  data->convertible = storage;
111  }
112 
113  static PyObject *convert(const Map &m) {
114  PyObject * obj = PyDict_New();
115  // memory should not leak
116  // but seeking for better approach.
117  boost::python::object *buffer = (boost::python::object *) malloc(2 * sizeof(boost::python::object));
118  boost::python::object *buffer_k = buffer + 0;
119  boost::python::object *buffer_v = buffer + 1;
120 
121  for (auto p: m) {
122  // for C++ 11 support
123  boost::python::object *kobj = new(buffer_k) boost::python::object(p.first);
124  boost::python::object *vobj = new(buffer_v) boost::python::object(p.second);
125  PyDict_SetItem(obj, kobj->ptr(), vobj->ptr());
126  }
127  free(buffer);
128  return obj;
129  }
130 
131  static const PyTypeObject *get_pytype() {
132  return &PyDict_Type;
133  }
134  };
135 }
136 
137 #endif //KNOWROB_PY_CONVERTER_PYTHON_TO_MAP_H
TermRule & string()
Definition: terms.cpp:63
void register_dict_to_map_converter()
Definition: dict.h:59
std::unordered_map< std::string, boost::any > dict_to_map(const boost::python::dict &py_dict)
Definition: dict.h:32
boost::any python_to_boost_any(const boost::python::object &obj)
Definition: dict.h:13
static void construct(PyObject *obj_ptr, boost::python::converter::rvalue_from_python_stage1_data *data)
Definition: dict.h:50
static void * convertible(PyObject *obj_ptr)
Definition: dict.h:45
static PyObject * convert(const Map &m)
Definition: dict.h:113
static const PyTypeObject * get_pytype()
Definition: dict.h:131
static void register_from_python_converter()
Definition: dict.h:68
static void register_to_python_converter()
Definition: dict.h:75
static void register_bidirectional_converter()
Definition: dict.h:79
static void * convertible(PyObject *obj)
Definition: dict.h:84
static void construct(PyObject *obj, boost::python::converter::rvalue_from_python_stage1_data *data)
Definition: dict.h:100