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>
16#include <boost/variant.hpp>
59 bool checkPythonObject(
const boost::python::object& pyObject,
const std::string&);
60 template<
typename Key,
typename Value>
61 bool checkPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
63 template<
typename Value>
64 bool checkPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
66 template<
typename Value>
67 bool checkPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
69 template<
typename... Types>
70 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
72 template<
typename... Types>
73 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
75 template<
typename Type>
76 bool checkPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&);
79 template<
typename Scalar>
83 std::shared_ptr<T>
convertPythonObject(
const boost::python::object& pyObject,
const std::shared_ptr<T>&);
85 template<
typename Key,
typename Value>
86 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&);
88 template<
typename Value>
89 std::vector<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::vector<Value>&);
91 template<
typename Value>
92 std::set<Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::set<Value>&);
94 template<
typename... Types>
95 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&);
97 template<
typename... Types>
98 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&);
100 template<
typename Type>
101 std::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&);
103 template<
typename Scalar>
105 template<
typename Value>
108 template<
typename Value>
110 template<
typename Key,
typename Value>
112 template<
typename... Types>
114 template<
typename... Types>
117 template<
typename Type>
120 template<
typename T>
struct Type;
122 template<typename T> struct
Type<std::set<T>>;
123 template<typename A, typename B> struct
Type<std::map<A, B> >;
124 template<typename... Types> struct
Type<std::tuple<Types...> >;
125 template<typename... Types> struct
Type<boost::variant<Types...> >;
126 template<> struct
Type<int>;
127 template<> struct
Type<bool>;
128 template<> struct
Type<float>;
129 template<> struct
Type<double>;
130 template<> struct
Type<std::string>;
132 template< typename T, typename... Types> struct
VariadicType;
148 template<
typename T>
struct Type {
static std::string
name() {
return "???";} };
152 template<
typename T>
struct Type<
std::set<T>> {
static std::string
name() {
return std::string(
"set(") +
Type<T>::name() +
")"; }};
157 template<>
struct Type<unsigned int> {
static std::string
name() {
return "unsigned int"; } };
159 template<>
struct Type<unsigned long int> {
static std::string
name() {
return "unsigned long int"; } };
161 template<>
struct Type<int> {
static std::string
name() {
return "int"; } };
163 template<>
struct Type<bool> {
static std::string
name() {
return "bool"; } };
165 template<>
struct Type<float> {
static std::string
name() {
return "float"; } };
167 template<>
struct Type<double> {
static std::string
name() {
return "float"; } };
169 template<>
struct Type<
std::string> {
static std::string
name() {
return "str"; } };
181 template<>
struct Type<
std::shared_ptr<Path>> {
183 static std::string
name() {
return std::string(
"Path"); }
188 template <
size_t >
struct SizeT { };
197 return PyBool_Check(pyObject.ptr());
203 return PyLong_CheckExact(pyObject.ptr());
208 return PyLong_CheckExact(pyObject.ptr());
214 return PyLong_CheckExact(pyObject.ptr());
220 return PyFloat_CheckExact(pyObject.ptr());
226 return PyFloat_CheckExact(pyObject.ptr());
232 return PyUnicode_Check(pyObject.ptr());
236 template<
typename Key,
typename Value>
239 if (not PyDict_Check(pyObject.ptr()))
return false;
240 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
241 boost::python::list keys = pyDict.keys();
242 boost::python::list values = pyDict.values();
243 for (
int i = 0; i < boost::python::len(keys); ++i) {
257 template<
class Functor>
260 boost::python::object iterator(boost::python::handle<>(PyObject_GetIter(pyObject.ptr())));
261 PyObject* item{
nullptr};
263 while ((item = PyIter_Next(iterator.ptr()))) {
264 boost::python::object obj{boost::python::handle<>(item)};
265 if (not function(obj))
return false;
271 template<
typename Value>
274 if (not PyList_Check(pyObject.ptr()))
return false;
280 template<
typename Value>
283 if (not PyAnySet_Check(pyObject.ptr()))
return false;
290 template<
typename... Types, std::size_t ... Is>
291 bool CheckTuple(
const std::tuple<Types...>& tuple,
const boost::python::tuple& pyTuple,
292 std::index_sequence<Is...>)
298 template<
typename... Types>
299 bool checkPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>& tuple)
301 if (not PyTuple_Check(pyObject.ptr()))
return false;
302 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
303 return CheckTuple(tuple, pyTuple, std::index_sequence_for<Types ...>());
307 template<
typename VariantType>
309 const boost::python::object&,
316 template<
typename... Types,
size_t N>
318 const boost::python::object& pyObject,
321 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
325 return CheckVariant(variant, pyObject, SizeT < N - 1 > ());
329 template<
typename... Types>
330 bool checkPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...> variant)
338 template<
typename Type>
354 template<
typename Scalar>
357 return boost::python::object(value);
366 template<
typename Value>
369 boost::python::list outputList;
370 for (
const auto& value :
vector) {
380 template<
typename Value>
383 boost::python::object result(boost::python::handle<>(PySet_New(
nullptr)));
384 for (
const auto& value : set) {
396 template<
typename Key,
typename Value>
399 boost::python::dict outputDict;
414 template <
typename TupleType >
415 inline void GetTuple(
const TupleType& tuple, boost::python::list& pyList)
417 GetTuple(tuple, pyList,
SizeT<std::tuple_size<TupleType>::value>());
421 template <
typename TupleType >
426 template <
typename TupleType,
size_t N >
429 GetTuple(tuple, pyList, SizeT < N - 1 > ());
440 template<
typename... Types>
443 boost::python::list outputList;
445 boost::python::tuple outputTuple(outputList);
468 template<
typename... Types>
481 template<
typename Type>
487 return boost::python::object();
502 template<
typename Scalar>
507 boost::python::extract<Scalar> valueProxy(pyObject);
508 if (valueProxy.check()) {
509 tmpValue =
static_cast<Scalar
>(valueProxy);
511 throw std::runtime_error(std::string(
"Could not convert value: Expected type '") +
Type<Scalar>::name() +
"' instead of '" +
512 pyObject.ptr()->ob_type->tp_name +
"'.");
525 template <
typename T>
526 __attribute__((noinline))
530 std::shared_ptr<T> tmpValue;
531 boost::python::extract<std::shared_ptr<T>> valueProxy(pyObject);
532 if (valueProxy.check()) {
533 tmpValue = valueProxy();
535 throw std::runtime_error(
536 std::string(
"Could not convert value: Expected type '") +
Type<std::shared_ptr<T>>::name() +
"' instead of '" +
537 pyObject.ptr()->ob_type->tp_name +
"'."
551 template<
typename Value>
555 std::vector<Value> tmpVector;
556 if (PyList_Check(pyObject.ptr()) or PyGen_Check(pyObject.ptr())) {
568 template<
typename Value>
571 std::set<Value> result;
572 if (PyAnySet_Check(pyObject.ptr())) {
590 template<
typename Key,
typename Value>
591 std::map<Key, Value>
convertPythonObject(
const boost::python::object& pyObject,
const std::map<Key, Value>&)
593 std::map<Key, Value> tmpMap;
594 const boost::python::dict& pyDict =
static_cast<const boost::python::dict&
>(pyObject);
595 boost::python::list keys = pyDict.keys();
597 for (
int i = 0; i < boost::python::len(keys); ++i) {
600 tmpMap.insert(std::pair<Key, Value>(key, value));
614 template <
typename TupleType >
615 inline void SetTuple(TupleType& tuple,
const boost::python::tuple& pyTuple)
617 static const unsigned N = std::tuple_size<TupleType>::value;
618 if ((
unsigned)boost::python::len(pyTuple) != N) {
619 throw std::runtime_error(std::string(
"Given python tuple has length ") +
620 std::to_string(boost::python::len(pyTuple)) +
621 ", expected " + std::to_string(N));
627 template <
typename TupleType >
632 template <
typename TupleType,
size_t N >
635 SetTuple(tuple, pyTuple, SizeT < N - 1 > ());
636 std::get < N - 1 > (tuple) =
convertPythonObject(pyTuple[N - 1], std::get < N - 1 > (tuple));
646 template<
typename... Types>
647 std::tuple<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const std::tuple<Types...>&)
649 std::tuple<Types...> tmpTuple;
650 const boost::python::tuple& pyTuple =
static_cast<const boost::python::tuple&
>(pyObject);
663 template <
typename... Types>
666 throw std::runtime_error(std::string(
"Could not set module parameter: Expected type '") +
667 Type<boost::variant<Types...> >::name() +
"' instead of '" +
668 pyObject.ptr()->ob_type->tp_name +
"'.");
672 template <
typename... Types,
size_t N >
673 inline void SetVariant(boost::variant<Types...>& variant,
const boost::python::object& pyObject,
SizeT<N>)
675 using Scalar =
typename std::tuple_element < N - 1, std::tuple<Types...> >::type;
681 }
catch (std::runtime_error& e) {
685 SetVariant(variant, pyObject, SizeT < N - 1 > ());
695 template<
typename... Types>
696 boost::variant<Types...>
convertPythonObject(
const boost::python::object& pyObject,
const boost::variant<Types...>&)
698 boost::variant<Types...> tmpVariant;
709 template<
typename Type>
710 std::optional<Type>
convertPythonObject(
const boost::python::object& pyObject,
const std::optional<Type>&)
712 std::optional<Type> tmpOptional = std::nullopt;
713 if (!pyObject.is_none()) {
Implements a path consisting of Module and/or Path objects.
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.
Python object converter utilities namespace.
boost::python::object convertToPythonObject(const Scalar &value)
------------— From C++ TO Python Converter ---------------------—
bool CheckVariant(const VariantType &, const boost::python::object &, SizeT< 0 >)
Recursion sentinel for the case that all former type checks failed for the variant.
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 ...
Scalar convertPythonObject(const boost::python::object &pyObject, Scalar)
Convert from Python to given type.
void SetTuple(TupleType &tuple, const boost::python::tuple &pyTuple)
TMP (Template Meta Programming ) The given python tuple is written into the given c++ tuple.
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.
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 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.
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.