aboutsummaryrefslogtreecommitdiffstats
path: root/common/pybindings.h
diff options
context:
space:
mode:
authorDavid Shah <davey1576@gmail.com>2018-06-07 12:59:27 +0200
committerDavid Shah <davey1576@gmail.com>2018-06-07 12:59:27 +0200
commit66b36cdd45532f157d3800bd1ed8078fc5a43950 (patch)
tree3b22d71f433df04b1945a62109e1a9d1f6ef0653 /common/pybindings.h
parent8bfeaeacedeb09133b8fb157c876fb90f41f5676 (diff)
parentb0e66d441cf584e7e48049d4f07afcc8e743309a (diff)
downloadnextpnr-66b36cdd45532f157d3800bd1ed8078fc5a43950.tar.gz
nextpnr-66b36cdd45532f157d3800bd1ed8078fc5a43950.tar.bz2
nextpnr-66b36cdd45532f157d3800bd1ed8078fc5a43950.zip
Merge branch 'python'
Signed-off-by: David Shah <davey1576@gmail.com>
Diffstat (limited to 'common/pybindings.h')
-rw-r--r--common/pybindings.h105
1 files changed, 43 insertions, 62 deletions
diff --git a/common/pybindings.h b/common/pybindings.h
index 5b2adc6a..a99ad51b 100644
--- a/common/pybindings.h
+++ b/common/pybindings.h
@@ -20,66 +20,23 @@
#ifndef COMMON_PYBINDINGS_H
#define COMMON_PYBINDINGS_H
+
+#include "pycontainers.h"
+
#include <utility>
#include <stdexcept>
#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 <Python.h>
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");
- }
- }
-
- static void wrap(const char *python_name) {
- class_<std::pair<T, T>>(python_name, no_init)
- .def("__next__", next);
- }
-};
-
-/*
-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
-*/
-
-template<typename T>
-struct range_wrapper {
- typedef decltype(std::declval<T>().begin()) iterator_t;
-
- static std::pair<iterator_t, iterator_t> iter(T &range) {
- return std::make_pair(range.begin(), range.end());
- }
-
- 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);
- }
-};
/*
A wrapper to enable custom type/ID to/from string conversions
*/
-template <typename T> struct string_wrapper {
+template<typename T>
+struct string_wrapper {
template<typename F>
struct from_pystring_converter {
from_pystring_converter() {
@@ -89,34 +46,37 @@ template <typename T> struct string_wrapper {
boost::python::type_id<T>());
};
- static void* convertible(PyObject* object) {
+ static void *convertible(PyObject *object) {
return PyUnicode_Check(object) ? object : 0;
}
static void construct(
- PyObject* object,
- converter::rvalue_from_python_stage1_data* data) {
- const wchar_t* value = PyUnicode_AsUnicode(object);
+ 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>*)
+ 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())));
+ new(storage) T(fn(std::string(value_ws.begin(), value_ws.end())));
data->convertible = storage;
}
- static F fn;
+ static F fn;
};
- template<typename F> struct to_str_wrapper {
+ template<typename F>
+ struct to_str_wrapper {
static F fn;
- std::string str(T& x) {
+
+ std::string str(T &x) {
return fn(x);
}
};
- template<typename F1, typename F2> static void wrap(const char *type_name, F1 to_str_fn, F2 from_str_fn) {
+ 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;
@@ -124,13 +84,34 @@ template <typename T> struct string_wrapper {
};
};
-#define WRAP_RANGE(t) range_wrapper<t##Range>().wrap(#t "Range", #t "Iterator")
+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();
+ }
+};
void init_python(const char *executable);
+
void deinit_python();
-void execute_python_file(const char* python_file);
+void execute_python_file(const char *python_file);
+
std::string parse_python_exception();
+
void arch_appendinittab();
#endif /* end of include guard: COMMON_PYBINDINGS_HH */