aboutsummaryrefslogtreecommitdiffstats
path: root/common/pybindings.h
diff options
context:
space:
mode:
Diffstat (limited to 'common/pybindings.h')
-rw-r--r--common/pybindings.h123
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 */