diff options
author | ZipCPU <dgisselq@ieee.org> | 2018-06-07 07:45:22 -0400 |
---|---|---|
committer | ZipCPU <dgisselq@ieee.org> | 2018-06-07 07:45:22 -0400 |
commit | 1ed5c641c16bffabe96ffd2ef8499dd3ae740050 (patch) | |
tree | e7b9417cb4faf44956859289dd6b9dfb579f96d9 /common/pybindings.h | |
parent | d7bb30cc66f2ba39c77a979b809a6e6bdfcb5097 (diff) | |
parent | ed0c44891fb510c8181c2ae9332d7a030f0aaaff (diff) | |
download | nextpnr-1ed5c641c16bffabe96ffd2ef8499dd3ae740050.tar.gz nextpnr-1ed5c641c16bffabe96ffd2ef8499dd3ae740050.tar.bz2 nextpnr-1ed5c641c16bffabe96ffd2ef8499dd3ae740050.zip |
Merge branch 'master' into gqtech
Diffstat (limited to 'common/pybindings.h')
-rw-r--r-- | common/pybindings.h | 123 |
1 files changed, 77 insertions, 46 deletions
diff --git a/common/pybindings.h b/common/pybindings.h index f594784c..bb060718 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -20,67 +20,98 @@ #ifndef COMMON_PYBINDINGS_H #define COMMON_PYBINDINGS_H -#include <utility> -#include <stdexcept> + +#include "pycontainers.h" + +#include <Python.h> #include <boost/python.hpp> -#include <boost/python/suite/indexing/vector_indexing_suite.hpp> -#include <boost/python/suite/indexing/map_indexing_suite.hpp> #include <boost/python/suite/indexing/map_indexing_suite.hpp> - +#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +#include <stdexcept> +#include <utility> using namespace boost::python; + /* -A wrapper for a Pythonised nextpnr Iterator. The actual class wrapped is a -pair<Iterator, Iterator> containing (current, end) -*/ - -template<typename T> -struct iterator_wrapper { - typedef decltype(*(std::declval<T>())) value_t; - - static value_t next(std::pair<T, T> &iter) { - if (iter.first != iter.second) { - value_t val = *iter.first; - ++iter.first; - return val; - } else { - PyErr_SetString(PyExc_StopIteration, "End of range reached"); - boost::python::throw_error_already_set(); - // Should be unreachable, but prevent control may reach end of non-void - throw std::runtime_error("unreachable"); +A wrapper to enable custom type/ID to/from string conversions + */ +template <typename T> struct string_wrapper +{ + template <typename F> struct from_pystring_converter + { + from_pystring_converter() + { + converter::registry::push_back(&convertible, &construct, + boost::python::type_id<T>()); + }; + + static void *convertible(PyObject *object) + { + return PyUnicode_Check(object) ? object : 0; } - } - static void wrap(const char *python_name) { - class_<std::pair<T, T>>(python_name, no_init) - .def("__next__", next); - } -}; + static void construct(PyObject *object, + converter::rvalue_from_python_stage1_data *data) + { + const wchar_t *value = PyUnicode_AsUnicode(object); + const std::wstring value_ws(value); + if (value == 0) + throw_error_already_set(); + void *storage = + ((boost::python::converter::rvalue_from_python_storage<T> *) + data) + ->storage.bytes; + new (storage) T(fn(std::string(value_ws.begin(), value_ws.end()))); + data->convertible = storage; + } -/* -A wrapper for a nextpnr Range. Ranges should have two functions, begin() -and end() which return iterator-like objects supporting ++, * and != -Full STL iterator semantics are not required, unlike the standard Boost wrappers -*/ + static F fn; + }; -template<typename T> -struct range_wrapper { - typedef decltype(std::declval<T>().begin()) iterator_t; + template <typename F> struct to_str_wrapper + { + static F fn; - static std::pair<iterator_t, iterator_t> iter(T &range) { - return std::make_pair(range.begin(), range.end()); - } + std::string str(T &x) { return fn(x); } + }; - static void wrap(const char *range_name, const char *iter_name) { - class_<T>(range_name, no_init) - .def("__iter__", iter); - iterator_wrapper<iterator_t>().wrap(iter_name); + template <typename F1, typename F2> + static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) + { + from_pystring_converter<F2>::fn = from_str_fn; + from_pystring_converter<F2>(); + to_str_wrapper<F1>::fn = to_str_fn; + class_<T>(type_name, no_init).def("__str__", to_str_wrapper<F1>::str); + }; +}; + +std::string parse_python_exception(); + +template <typename Tn> void python_export_global(const char *name, Tn &x) +{ + PyObject *m, *d; + m = PyImport_AddModule("__main__"); + if (m == NULL) + return; + d = PyModule_GetDict(m); + try { + PyObject *p = incref(object(boost::ref(x)).ptr()); + PyDict_SetItemString(d, name, p); + } catch (boost::python::error_already_set const &) { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + std::terminate(); } }; -#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator") +void init_python(const char *executable); + +void deinit_python(); + +void execute_python_file(const char *python_file); -void execute_python_file(const char *executable, const char* python_file); std::string parse_python_exception(); + void arch_appendinittab(); #endif /* end of include guard: COMMON_PYBINDINGS_HH */ |