11 #include <boost/python/object.hpp>
12 #include <boost/python/list.hpp>
13 #include <boost/python/tuple.hpp>
14 #include <boost/python/dict.hpp>
15 #include <boost/python/extract.hpp>
17 #include <boost/variant.hpp>
18 #include <boost/optional.hpp>
41 namespace PyObjConvUtils {
60 bool checkPythonObject(
const boost::python::object& pyObject,
const std::string&);
61 template<
typename Key,
typename Value>
62 bool checkPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
64 template<
typename Value>
65 bool checkPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
67 template<
typename Value>
68 bool checkPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
70 template<
typename... Types>
71 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
73 template<
typename... Types>
74 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
76 template<
typename Type>
77 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::optional<Type>&);
80 template<
typename Scalar>
83 template<
typename Key,
typename Value>
84 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
86 template<
typename Value>
87 std::vector<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
89 template<
typename Value>
90 std::set<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
92 template<
typename... Types>
93 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
95 template<
typename... Types>
96 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
98 template<
typename Type>
99 boost::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const boost::optional<Type>&);
101 template<
typename Scalar>
103 template<
typename Value>
106 template<
typename Value>
108 template<
typename Key,
typename Value>
110 template<
typename... Types>
112 template<
typename... Types>
115 template<
typename Type>
118 template<
typename T>
struct Type;
119 template<
typename T>
struct Type<std::vector<T> >;
120 template<typename T> struct
Type<std::set<T>>;
121 template<typename A, typename B> struct
Type<std::map<A, B> >;
122 template<typename... Types> struct
Type<std::tuple<Types...> >;
123 template<typename... Types> struct
Type<boost::variant<Types...> >;
124 template<> struct
Type<int>;
125 template<> struct
Type<bool>;
126 template<> struct
Type<float>;
127 template<> struct
Type<double>;
128 template<> struct
Type<std::string>;
130 template< typename T, typename... Types> struct
VariadicType;
146 template<
typename T>
struct Type {
static std::string
name() {
return "???";} };
148 template<
typename T>
struct Type<std::vector<T> > {
static std::string
name() {
return std::string(
"list(") +
Type<T>::name() +
")"; } };
150 template<
typename T>
struct Type<std::set<T>> {
static std::string
name() {
return std::string(
"set(") +
Type<T>::name() +
")"; }};
155 template<>
struct Type<unsigned int> {
static std::string
name() {
return "unsigned int"; } };
157 template<>
struct Type<unsigned long int> {
static std::string
name() {
return "unsigned long int"; } };
159 template<>
struct Type<int> {
static std::string
name() {
return "int"; } };
161 template<>
struct Type<bool> {
static std::string
name() {
return "bool"; } };
163 template<>
struct Type<float> {
static std::string
name() {
return "float"; } };
165 template<>
struct Type<double> {
static std::string
name() {
return "float"; } };
167 template<>
struct Type<std::string> {
static std::string
name() {
return "str"; } };
170 template<
typename T>
struct Type<boost::optional<T>> {
static std::string
name() {
return Type<T>::name() +
" or None"; } };
179 template<>
struct Type<std::shared_ptr<Path>> {
181 static std::string
name() {
return std::string(
"Path"); }
186 template <
size_t >
struct SizeT { };
195 return PyBool_Check(pyObject.ptr());
201 return PyLong_CheckExact(pyObject.ptr());
206 return PyLong_CheckExact(pyObject.ptr());
212 return PyLong_CheckExact(pyObject.ptr());
218 return PyFloat_CheckExact(pyObject.ptr());
224 return PyFloat_CheckExact(pyObject.ptr());
230 return PyUnicode_Check(pyObject.ptr());
234 template<
typename Key,
typename Value>
237 if (not PyDict_Check(pyObject.ptr()))
return false;
238 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
239 boost::python::list keys = pyDict.keys();
240 boost::python::list values = pyDict.values();
241 for (
int i = 0; i < boost::python::len(keys); ++i) {
255 template<
class Functor>
258 boost::python::object iterator(boost::python::handle<>(PyObject_GetIter(pyObject.ptr())));
259 PyObject* item{
nullptr};
261 while ((item = PyIter_Next(iterator.ptr()))) {
262 boost::python::object obj{boost::python::handle<>(item)};
263 if (not
function(obj))
return false;
269 template<
typename Value>
272 if (not PyList_Check(pyObject.ptr()))
return false;
278 template<
typename Value>
281 if (not PyAnySet_Check(pyObject.ptr()))
return false;
288 template<
typename... Types, std::size_t ... Is>
289 bool CheckTuple(
const std::tuple<Types...>& tuple,
const boost::python::tuple& pyTuple,
290 std::index_sequence<Is...>)
296 template<
typename... Types>
297 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>& tuple)
299 if (not PyTuple_Check(pyObject.ptr()))
return false;
300 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
301 return CheckTuple(tuple, pyTuple, std::index_sequence_for<Types ...>());
305 template<
typename VariantType>
307 const boost::python::object&,
314 template<
typename... Types,
size_t N>
316 const boost::python::object& pyObject,
319 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
327 template<
typename... Types>
328 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...> variant)
336 template<
typename Type>
352 template<
typename Scalar>
355 return boost::python::object(value);
364 template<
typename Value>
367 boost::python::list outputList;
368 for (
const auto& value : vector) {
378 template<
typename Value>
381 boost::python::object result(boost::python::handle<>(PySet_New(
nullptr)));
382 for (
const auto& value : set) {
394 template<
typename Key,
typename Value>
397 boost::python::dict outputDict;
398 for (
auto pair : map) {
412 template <
typename TupleType >
413 inline void GetTuple(
const TupleType& tuple, boost::python::list& pyList)
415 GetTuple(tuple, pyList,
SizeT<std::tuple_size<TupleType>::value>());
419 template <
typename TupleType >
424 template <
typename TupleType,
size_t N >
438 template<
typename... Types>
441 boost::python::list outputList;
443 boost::python::tuple outputTuple(outputList);
466 template<
typename... Types>
479 template<
typename Type>
485 return boost::python::object();
500 template<
typename Scalar>
505 boost::python::extract<Scalar> valueProxy(pyObject);
506 if (valueProxy.check()) {
507 tmpValue =
static_cast<Scalar
>(valueProxy);
509 throw std::runtime_error(std::string(
"Could not convert value: Expected type '") +
Type<Scalar>::name() +
"' instead of '" +
510 pyObject.ptr()->ob_type->tp_name +
"'.");
523 template<
typename Value>
527 std::vector<Value> tmpVector;
528 if (PyList_Check(pyObject.ptr()) or PyGen_Check(pyObject.ptr())) {
540 template<
typename Value>
543 std::set<Value> result;
544 if (PyAnySet_Check(pyObject.ptr())) {
562 template<
typename Key,
typename Value>
563 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&)
565 std::map<Key, Value> tmpMap;
566 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
567 boost::python::list keys = pyDict.keys();
569 for (
int i = 0; i < boost::python::len(keys); ++i) {
572 tmpMap.insert(std::pair<Key, Value>(key, value));
586 template <
typename TupleType >
587 inline void SetTuple(TupleType& tuple,
const boost::python::tuple& pyTuple)
589 static const unsigned N = std::tuple_size<TupleType>::value;
590 if ((
unsigned)boost::python::len(pyTuple) != N) {
591 throw std::runtime_error(std::string(
"Given python tuple has length ") +
592 std::to_string(boost::python::len(pyTuple)) +
593 ", expected " + std::to_string(N));
599 template <
typename TupleType >
604 template <
typename TupleType,
size_t N >
608 std::get < N - 1 > (tuple) =
convertPythonObject(pyTuple[N - 1], std::get < N - 1 > (tuple));
618 template<
typename... Types>
619 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&)
621 std::tuple<Types...> tmpTuple;
622 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
635 template <
typename... Types>
638 throw std::runtime_error(std::string(
"Could not set module parameter: Expected type '") +
639 Type<boost::variant<Types...> >::name() +
"' instead of '" +
640 pyObject.ptr()->ob_type->tp_name +
"'.");
644 template <
typename... Types,
size_t N >
645 inline void SetVariant(boost::variant<Types...>& variant,
const boost::python::object& pyObject,
SizeT<N>)
647 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
653 }
catch (std::runtime_error& e) {
667 template<
typename... Types>
668 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&)
670 boost::variant<Types...> tmpVariant;
681 template<
typename Type>
682 boost::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const boost::optional<Type>&)
684 boost::optional<Type> tmpOptional = boost::none;
685 if (!pyObject.is_none()) {
Helper function object to unpack a value from a variant to a python object.
boost::python::object operator()(const T &value) const
actually convert a value.
boost::python::object convertToPythonObject(const Scalar &value)
------------— From C++ TO Python Converter ---------------------—
void GetTuple(const TupleType &tuple, boost::python::list &pyList)
TMP (Template Meta Programming ) The given python list is filled, and later converted into a python t...
void SetTuple(TupleType &tuple, const boost::python::tuple &pyTuple)
TMP (Template Meta Programming ) The given python tuple is written into the given c++ tuple.
Scalar convertPythonObject(const boost::python::object &pyObject, Scalar)
Convert from Python to given type.
bool CheckVariant(const VariantType &, const boost::python::object &, SizeT< 0 >)
Recursion sentinal for the case that all former type checks failed for the variant.
void SetVariant(boost::variant< Types... > &, const boost::python::object &pyObject, SizeT< 0 >)
TMP (Template Meta Programming ) The given python object is written into the given c++ boost variant.
bool CheckTuple(const std::tuple< Types... > &tuple, const boost::python::tuple &pyTuple, std::index_sequence< Is... >)
Check if all tuple elements match.
bool checkPythonObject(const boost::python::object &pyObject, bool)
check if the python object can be converted to the given type.
bool iteratePythonObject(const boost::python::object &pyObject, Functor function)
Helper function to loop over a python object that implements the iterator concept and call a functor ...
Abstract base class for different kinds of events.
Helper construct for TMP that provides an index at compile time to recurse through type lists.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name
static std::string name()
type name
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
static std::string name()
type name.
Converts a template argument into a string for corresponding Python type.
static std::string name()
type name.
static std::string name()
type name.
Recursively convert multiple types to type names (used for tuples).
static std::string name()
type name.