cxtream  0.5.1
C++17 data pipeline with Python bindings.
pyboost_column_converter.hpp
1 /****************************************************************************
2  * cxtream library
3  * Copyright (c) 2017, Cognexa Solutions s.r.o.
4  * Author(s) Filip Matzner
5  *
6  * This file is distributed under the MIT License.
7  * See the accompanying file LICENSE.txt for the complete license agreement.
8  ****************************************************************************/
9 
10 #ifndef CXTREAM_PYTHON_UTILITY_PYBOOST_COLUMN_CONVERTER_HPP
11 #define CXTREAM_PYTHON_UTILITY_PYBOOST_COLUMN_CONVERTER_HPP
12 
13 #include <cxtream/core/utility/tuple.hpp>
14 #include <cxtream/python/range.hpp>
15 #include <cxtream/python/utility/pyboost_ndarray_converter.hpp>
16 
17 #include <boost/python.hpp>
18 
19 #include <stdexcept>
20 #include <string>
21 #include <vector>
22 
23 namespace cxtream::python::utility {
24 
25 // recursive transformation from a multidimensional vector to python //
26 
27 namespace detail {
28 
29  // conversion of std::vector to a Python list-like type //
30  // Vectors of builtin primitive types (e.g., int, bool, ...) are converted
31  // to numpy ndarrays. Vector of other types are converted to lists and
32  // their elements are converted using boost::python::object
33 
34  template<typename T>
35  struct vector_to_python_impl {
36  static PyObject* impl(T val)
37  {
38  boost::python::object obj{std::move(val)};
39  Py_INCREF(obj.ptr());
40  return obj.ptr();
41  }
42  };
43 
44  template<typename T>
45  struct vector_to_python_impl<std::vector<T>> {
46  static PyObject* impl(std::vector<T> vec)
47  {
48  if (std::is_arithmetic<T>{}) {
49  return utility::to_ndarray(std::move(vec));
50  }
51 
52  PyObject* list{PyList_New(vec.size())};
53  if (!list) throw std::runtime_error{"Unable to create Python list."};
54  for (std::size_t i = 0; i < vec.size(); ++i) {
55  PyList_SET_ITEM(list, i, vector_to_python_impl<T>::impl(std::move(vec[i])));
56  }
57  return list;
58  }
59  };
60 
61 } // namespace detail
62 
68 template<typename T>
69 boost::python::object to_python(std::vector<T> v)
70 {
71  namespace py = boost::python;
72  py::handle<> py_obj_handle{detail::vector_to_python_impl<std::vector<T>>::impl(std::move(v))};
73  return py::object{py_obj_handle};
74 }
75 
83 template<typename Tuple>
84 boost::python::dict columns_to_python(Tuple tuple)
85 {
86  boost::python::dict res;
87  cxtream::utility::tuple_for_each(tuple, [&res](auto& column) {
88  res[column.name()] = to_python(std::move(column.value()));
89  });
90  return res;
91 }
92 
93 } // namespace cxtream::python::utility
94 #endif
STL namespace.
boost::python::object to_python(std::vector< T > v)
Create a Python list-like object out of a multidimensional std::vector.
constexpr auto tuple_for_each(Tuple &&tuple, Fun &&fun)
Apply a function on each element of a tuple.
Definition: tuple.hpp:120
boost::python::dict columns_to_python(Tuple tuple)
Convert a tuple of cxtream columns into a Python dict.
PyObject * to_ndarray(const std::vector< T > &vec)
Build ndarray from a one dimensional std::vector.