HiPipe  0.7.0
C++17 data pipeline with Python bindings.
ndim_vector_converter.hpp
1 /****************************************************************************
2  * hipipe library
3  * Copyright (c) 2017, Cognexa Solutions s.r.o.
4  * Copyright (c) 2018, Iterait a.s.
5  * Author(s) Filip Matzner
6  *
7  * This file is distributed under the MIT License.
8  * See the accompanying file LICENSE.txt for the complete license agreement.
9  ****************************************************************************/
10 
11 #pragma once
12 #include <hipipe/build_config.hpp>
13 #ifdef HIPIPE_BUILD_PYTHON
14 
15 #include <hipipe/core/python/range.hpp>
16 #include <hipipe/core/python/utility/vector_converter.hpp>
17 
18 #include <boost/python.hpp>
19 
20 #include <stdexcept>
21 #include <string>
22 #include <vector>
23 
24 namespace hipipe::python::utility {
25 
26 // recursive transformation from a multidimensional vector to python //
27 
28 namespace detail {
29 
30  // conversion of std::vector to a Python list-like type //
31  // Vectors of builtin primitive types (e.g., int, bool, ...) are converted
32  // to numpy ndarrays. Vector of other types are converted to lists and
33  // their elements are converted using boost::python::object
34 
35  template<typename T>
36  struct vector_to_python_impl {
37  static PyObject* impl(T val)
38  {
39  boost::python::object obj{std::move(val)};
40  Py_INCREF(obj.ptr());
41  return obj.ptr();
42  }
43  };
44 
45  template<typename T>
46  struct vector_to_python_impl<std::vector<T>> {
47  static PyObject* impl(std::vector<T> vec)
48  {
49  if (std::is_arithmetic<T>{}) {
50  return utility::to_ndarray(std::move(vec));
51  }
52 
53  PyObject* list{PyList_New(vec.size())};
54  if (!list) throw std::runtime_error{"Unable to create Python list."};
55  for (std::size_t i = 0; i < vec.size(); ++i) {
56  PyList_SET_ITEM(list, i, vector_to_python_impl<T>::impl(std::move(vec[i])));
57  }
58  return list;
59  }
60  };
61 
62 } // namespace detail
63 
69 template<typename T>
70 boost::python::object to_python(std::vector<T> v)
71 {
72  namespace py = boost::python;
73  py::handle<> py_obj_handle{detail::vector_to_python_impl<std::vector<T>>::impl(std::move(v))};
74  return py::object{py_obj_handle};
75 }
76 
77 } // namespace hipipe::python::utility
78 
79 #endif // HIPIPE_BUILD_PYTHON