diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/handle_error.cc | 32 | ||||
-rw-r--r-- | common/pybindings.cc | 64 | ||||
-rw-r--r-- | common/pybindings.h | 13 | ||||
-rw-r--r-- | common/pycontainers.h | 170 | ||||
-rw-r--r-- | common/pywrappers.h | 52 |
5 files changed, 154 insertions, 177 deletions
diff --git a/common/handle_error.cc b/common/handle_error.cc index a091f07e..d5542369 100644 --- a/common/handle_error.cc +++ b/common/handle_error.cc @@ -1,10 +1,10 @@ #ifndef NO_PYTHON #include <Python.h> -#include <boost/python.hpp> +#include <pybind11/pybind11.h> #include "nextpnr.h" -namespace py = boost::python; +namespace py = pybind11; NEXTPNR_NAMESPACE_BEGIN @@ -20,42 +20,36 @@ std::string parse_python_exception() std::string ret("Unfetchable Python error"); // If the fetch got a type pointer, parse the type into the exception string if (type_ptr != NULL) { - py::handle<> h_type(type_ptr); - py::str type_pstr(h_type); - // Extract the string from the boost::python object - py::extract<std::string> e_type_pstr(type_pstr); + py::object obj = py::reinterpret_borrow<py::object>(type_ptr); // If a valid string extraction is available, use it // otherwise use fallback - if (e_type_pstr.check()) - ret = e_type_pstr(); + if (py::isinstance<py::str>(obj)) + ret = obj.cast<std::string>(); else ret = "Unknown exception type"; } // Do the same for the exception value (the stringification of the // exception) if (value_ptr != NULL) { - py::handle<> h_val(value_ptr); - py::str a(h_val); - py::extract<std::string> returned(a); - if (returned.check()) - ret += ": " + returned(); + py::object obj = py::reinterpret_borrow<py::object>(value_ptr); + if (py::isinstance<py::str>(obj)) + ret += ": " + obj.cast<std::string>(); else ret += std::string(": Unparseable Python error: "); } // Parse lines from the traceback using the Python traceback module if (traceback_ptr != NULL) { - py::handle<> h_tb(traceback_ptr); + py::handle h_tb(traceback_ptr); // Load the traceback module and the format_tb function - py::object tb(py::import("traceback")); + py::object tb(py::module::import("traceback")); py::object fmt_tb(tb.attr("format_tb")); // Call format_tb to get a list of traceback strings py::object tb_list(fmt_tb(h_tb)); // Join the traceback strings into a single string - py::object tb_str(py::str("\n").join(tb_list)); + py::object tb_str(py::str("\n") + tb_list); // Extract the string, check the extraction, and fallback in necessary - py::extract<std::string> returned(tb_str); - if (returned.check()) - ret += ": " + returned(); + if (py::isinstance<py::str>(tb_str)) + ret += ": " + tb_str.cast<std::string>(); else ret += std::string(": Unparseable Python traceback"); } diff --git a/common/pybindings.cc b/common/pybindings.cc index 51da00e9..49acb996 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -43,7 +43,7 @@ NEXTPNR_NAMESPACE_BEGIN // Architecture-specific bindings should be created in the below function, which // must be implemented in all architectures -void arch_wrap_python(); +void arch_wrap_python(py::module &m); bool operator==(const PortRef &a, const PortRef &b) { return (a.cell == b.cell) && (a.port == b.port); } @@ -90,13 +90,13 @@ template <> struct string_converter<Property> } // namespace PythonConversion -BOOST_PYTHON_MODULE(MODULE_NAME) +PYBIND11_MODULE(MODULE_NAME, m) { - register_exception_translator<assertion_failure>(&translate_assertfail); + //register_exception_translator<assertion_failure>(&translate_assertfail); using namespace PythonConversion; - enum_<GraphicElement::type_t>("GraphicElementType") + py::enum_<GraphicElement::type_t>(m, "GraphicElementType") .value("TYPE_NONE", GraphicElement::TYPE_NONE) .value("TYPE_LINE", GraphicElement::TYPE_LINE) .value("TYPE_ARROW", GraphicElement::TYPE_ARROW) @@ -105,7 +105,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .value("TYPE_LABEL", GraphicElement::TYPE_LABEL) .export_values(); - enum_<GraphicElement::style_t>("GraphicElementStyle") + py::enum_<GraphicElement::style_t>(m, "GraphicElementStyle") .value("STYLE_GRID", GraphicElement::STYLE_GRID) .value("STYLE_FRAME", GraphicElement::STYLE_FRAME) .value("STYLE_HIDDEN", GraphicElement::STYLE_HIDDEN) @@ -113,9 +113,11 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .value("STYLE_ACTIVE", GraphicElement::STYLE_ACTIVE) .export_values(); - class_<GraphicElement>("GraphicElement") - .def(init<GraphicElement::type_t, GraphicElement::style_t, float, float, float, float, float>( - (args("type"), "style", "x1", "y1", "x2", "y2", "z"))) + py::class_<GraphicElement>(m, "GraphicElement") + .def(py::init<GraphicElement::type_t, GraphicElement::style_t, float, float, float, float, float>( + //FIXME + //(args("type"), "style", "x1", "y1", "x2", "y2", "z") + )) .def_readwrite("type", &GraphicElement::type) .def_readwrite("x1", &GraphicElement::x1) .def_readwrite("y1", &GraphicElement::y1) @@ -123,13 +125,13 @@ BOOST_PYTHON_MODULE(MODULE_NAME) .def_readwrite("y2", &GraphicElement::y2) .def_readwrite("text", &GraphicElement::text); - enum_<PortType>("PortType") + py::enum_<PortType>(m, "PortType") .value("PORT_IN", PORT_IN) .value("PORT_OUT", PORT_OUT) .value("PORT_INOUT", PORT_INOUT) .export_values(); - enum_<PlaceStrength>("PlaceStrength") + py::enum_<PlaceStrength>(m, "PlaceStrength") .value("STRENGTH_NONE", STRENGTH_NONE) .value("STRENGTH_WEAK", STRENGTH_WEAK) .value("STRENGTH_STRONG", STRENGTH_STRONG) @@ -143,15 +145,15 @@ BOOST_PYTHON_MODULE(MODULE_NAME) typedef std::unordered_map<IdString, IdString> IdIdMap; typedef std::unordered_map<IdString, std::unique_ptr<Region>> RegionMap; - class_<BaseCtx, BaseCtx *, boost::noncopyable>("BaseCtx", no_init); + py::class_<BaseCtx, std::unique_ptr<BaseCtx, py::nodelete>>(m, "BaseCtx"); - auto loc_cls = class_<Loc>("Loc") - .def(init<int, int, int>()) + auto loc_cls = py::class_<Loc>(m, "Loc") + .def(py::init<int, int, int>()) .def_readwrite("x", &Loc::x) .def_readwrite("y", &Loc::y) .def_readwrite("z", &Loc::z); - auto ci_cls = class_<ContextualWrapper<CellInfo &>>("CellInfo", no_init); + auto ci_cls = py::class_<ContextualWrapper<CellInfo &>>(m, "CellInfo"); readwrite_wrapper<CellInfo &, decltype(&CellInfo::name), &CellInfo::name, conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(ci_cls, "name"); readwrite_wrapper<CellInfo &, decltype(&CellInfo::type), &CellInfo::type, conv_to_str<IdString>, @@ -185,7 +187,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) fn_wrapper_1a_v<CellInfo &, decltype(&CellInfo::unsetAttr), &CellInfo::unsetAttr, conv_from_str<IdString>>::def_wrap(ci_cls, "unsetAttr"); - auto pi_cls = class_<ContextualWrapper<PortInfo &>>("PortInfo", no_init); + auto pi_cls = py::class_<ContextualWrapper<PortInfo &>>(m, "PortInfo"); readwrite_wrapper<PortInfo &, decltype(&PortInfo::name), &PortInfo::name, conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(pi_cls, "name"); readonly_wrapper<PortInfo &, decltype(&PortInfo::net), &PortInfo::net, deref_and_wrap<NetInfo>>::def_wrap(pi_cls, @@ -198,7 +200,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) typedef std::unordered_set<BelId> BelSet; typedef std::unordered_set<WireId> WireSet; - auto ni_cls = class_<ContextualWrapper<NetInfo &>>("NetInfo", no_init); + auto ni_cls = py::class_<ContextualWrapper<NetInfo &>>(m, "NetInfo"); readwrite_wrapper<NetInfo &, decltype(&NetInfo::name), &NetInfo::name, conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(ni_cls, "name"); readwrite_wrapper<NetInfo &, decltype(&NetInfo::driver), &NetInfo::driver, wrap_context<PortRef &>, @@ -208,7 +210,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readonly_wrapper<NetInfo &, decltype(&NetInfo::wires), &NetInfo::wires, wrap_context<WireMap &>>::def_wrap(ni_cls, "wires"); - auto pr_cls = class_<ContextualWrapper<PortRef &>>("PortRef", no_init); + auto pr_cls = py::class_<ContextualWrapper<PortRef &>>(m, "PortRef"); readonly_wrapper<PortRef &, decltype(&PortRef::cell), &PortRef::cell, deref_and_wrap<CellInfo>>::def_wrap(pr_cls, "cell"); readwrite_wrapper<PortRef &, decltype(&PortRef::port), &PortRef::port, conv_to_str<IdString>, @@ -216,16 +218,16 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readwrite_wrapper<PortRef &, decltype(&PortRef::budget), &PortRef::budget, pass_through<delay_t>, pass_through<delay_t>>::def_wrap(pr_cls, "budget"); - auto pm_cls = class_<ContextualWrapper<PipMap &>>("PipMap", no_init); + auto pm_cls = py::class_<ContextualWrapper<PipMap &>>(m, "PipMap"); readwrite_wrapper<PipMap &, decltype(&PipMap::pip), &PipMap::pip, conv_to_str<PipId>, conv_from_str<PipId>>::def_wrap(pm_cls, "pip"); readwrite_wrapper<PipMap &, decltype(&PipMap::strength), &PipMap::strength, pass_through<PlaceStrength>, pass_through<PlaceStrength>>::def_wrap(pm_cls, "strength"); - def("parse_json", parse_json_shim); - def("load_design", load_design_shim, return_value_policy<manage_new_object>()); + m.def("parse_json", parse_json_shim); + m.def("load_design", load_design_shim, py::return_value_policy::take_ownership); - auto region_cls = class_<ContextualWrapper<Region &>>("Region", no_init); + auto region_cls = py::class_<ContextualWrapper<Region &>>(m, "Region"); readwrite_wrapper<Region &, decltype(&Region::name), &Region::name, conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(region_cls, "name"); readwrite_wrapper<Region &, decltype(&Region::constr_bels), &Region::constr_bels, pass_through<bool>, @@ -239,7 +241,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readonly_wrapper<Region &, decltype(&Region::wires), &Region::wires, wrap_context<WireSet &>>::def_wrap(region_cls, "wires"); - auto hierarchy_cls = class_<ContextualWrapper<HierarchicalCell &>>("HierarchicalCell", no_init); + auto hierarchy_cls = py::class_<ContextualWrapper<HierarchicalCell &>>(m, "HierarchicalCell"); readwrite_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::name), &HierarchicalCell::name, conv_to_str<IdString>, conv_from_str<IdString>>::def_wrap(hierarchy_cls, "name"); readwrite_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::type), &HierarchicalCell::type, @@ -255,15 +257,15 @@ BOOST_PYTHON_MODULE(MODULE_NAME) wrap_context<IdIdMap &>>::def_wrap(hierarchy_cls, "nets"); readonly_wrapper<HierarchicalCell &, decltype(&HierarchicalCell::hier_cells), &HierarchicalCell::hier_cells, wrap_context<IdIdMap &>>::def_wrap(hierarchy_cls, "hier_cells"); - WRAP_MAP(AttrMap, conv_to_str<Property>, "AttrMap"); - WRAP_MAP(PortMap, wrap_context<PortInfo &>, "PortMap"); - WRAP_MAP(IdIdMap, conv_to_str<IdString>, "IdIdMap"); - WRAP_MAP(WireMap, wrap_context<PipMap &>, "WireMap"); - WRAP_MAP_UPTR(RegionMap, "RegionMap"); + WRAP_MAP(m, AttrMap, conv_to_str<Property>, "AttrMap"); + WRAP_MAP(m, PortMap, wrap_context<PortInfo &>, "PortMap"); + WRAP_MAP(m, IdIdMap, conv_to_str<IdString>, "IdIdMap"); + WRAP_MAP(m, WireMap, wrap_context<PipMap &>, "WireMap"); + WRAP_MAP_UPTR(m, RegionMap, "RegionMap"); - WRAP_VECTOR(PortRefVector, wrap_context<PortRef &>); + WRAP_VECTOR(m, PortRefVector, wrap_context<PortRef &>); - arch_wrap_python(); + arch_wrap_python(m); } #ifdef MAIN_EXECUTABLE @@ -291,7 +293,7 @@ void init_python(const char *executable, bool first) PyImport_ImportModule(TOSTRING(MODULE_NAME)); PyRun_SimpleString("from " TOSTRING(MODULE_NAME) " import *"); - } catch (boost::python::error_already_set const &) { + } catch (py::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; @@ -321,7 +323,7 @@ void execute_python_file(const char *python_file) if (result == -1) { log_error("Error occurred while executing Python script %s\n", python_file); } - } catch (boost::python::error_already_set const &) { + } catch (py::error_already_set const &) { // Parse and output the exception std::string perror_str = parse_python_exception(); log_error("Error in Python: %s\n", perror_str.c_str()); diff --git a/common/pybindings.h b/common/pybindings.h index c4d84442..4923c821 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -22,11 +22,10 @@ #define COMMON_PYBINDINGS_H #include <Python.h> -#include <boost/python.hpp> -#include <boost/python/suite/indexing/map_indexing_suite.hpp> -#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +#include <pybind11/pybind11.h> #include <stdexcept> #include <utility> +#include <iostream> #include "pycontainers.h" #include "pywrappers.h" @@ -34,7 +33,7 @@ NEXTPNR_NAMESPACE_BEGIN -using namespace boost::python; +namespace py = pybind11; std::string parse_python_exception(); @@ -46,9 +45,9 @@ template <typename Tn> void python_export_global(const char *name, Tn &x) 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 &) { + py::object obj = py::cast(x); + PyDict_SetItemString(d, name, obj.ptr()); + } catch (py::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; diff --git a/common/pycontainers.h b/common/pycontainers.h index 2b9ee208..15e502d1 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -21,9 +21,7 @@ #ifndef COMMON_PYCONTAINERS_H #define COMMON_PYCONTAINERS_H -#include <boost/python.hpp> -#include <boost/python/suite/indexing/map_indexing_suite.hpp> -#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +#include <pybind11/pybind11.h> #include <sstream> #include <stdexcept> #include <type_traits> @@ -33,12 +31,12 @@ NEXTPNR_NAMESPACE_BEGIN -using namespace boost::python; +namespace py = pybind11; inline void KeyError() { PyErr_SetString(PyExc_KeyError, "Key not found"); - boost::python::throw_error_already_set(); + throw py::error_already_set(); } /* @@ -47,7 +45,7 @@ pair<Iterator, Iterator> containing (current, end), wrapped in a ContextualWrapp */ -template <typename T, typename P, typename value_conv = PythonConversion::pass_through<T>> struct iterator_wrapper +template <typename T, py::return_value_policy P, typename value_conv = PythonConversion::pass_through<T>> struct iterator_wrapper { typedef decltype(*(std::declval<T>())) value_t; @@ -62,16 +60,13 @@ template <typename T, typename P, typename value_conv = PythonConversion::pass_t 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"); + throw py::error_already_set(); } } - static void wrap(const char *python_name) + static void wrap(py::module &m, const char *python_name) { - class_<wrapped_iter_t>(python_name, no_init).def("__next__", next, P()); + py::class_<wrapped_iter_t>(m, python_name).def("__next__", next, P); } }; @@ -81,7 +76,7 @@ and end() which return iterator-like objects supporting ++, * and != Full STL iterator semantics are not required, unlike the standard Boost wrappers */ -template <typename T, typename P = return_value_policy<return_by_value>, +template <typename T, py::return_value_policy P = py::return_value_policy::copy, typename value_conv = PythonConversion::pass_through<T>> struct range_wrapper { @@ -110,23 +105,23 @@ struct range_wrapper return ss.str(); } - static void wrap(const char *range_name, const char *iter_name) + static void wrap(py::module &m, const char *range_name, const char *iter_name) { - class_<wrapped_range>(range_name, no_init).def("__iter__", iter).def("__repr__", repr); - iterator_wrapper<iterator_t, P, value_conv>().wrap(iter_name); + py::class_<wrapped_range>(m, range_name).def("__iter__", iter).def("__repr__", repr); + iterator_wrapper<iterator_t, P, value_conv>().wrap(m, iter_name); } typedef iterator_wrapper<iterator_t, P, value_conv> iter_wrap; }; -#define WRAP_RANGE(t, conv) \ - range_wrapper<t##Range, return_value_policy<return_by_value>, conv>().wrap(#t "Range", #t "Iterator") +#define WRAP_RANGE(m, t, conv) \ + range_wrapper<t##Range, py::return_value_policy::copy, conv>().wrap(m, #t "Range", #t "Iterator") /* A wrapper for a vector or similar structure. With support for conversion */ -template <typename T, typename P = return_value_policy<return_by_value>, +template <typename T, py::return_value_policy P = py::return_value_policy::copy, typename value_conv = PythonConversion::pass_through<T>> struct vector_wrapper { @@ -163,21 +158,21 @@ struct vector_wrapper return value_conv()(range.ctx, boost::ref(range.base.at(i))); } - static void wrap(const char *range_name, const char *iter_name) + static void wrap(py::module &m, const char *range_name, const char *iter_name) { - class_<wrapped_vector>(range_name, no_init) + py::class_<wrapped_vector>(m, range_name) .def("__iter__", iter) .def("__repr__", repr) .def("__len__", len) .def("__getitem__", getitem); - iterator_wrapper<iterator_t, P, value_conv>().wrap(iter_name); + iterator_wrapper<iterator_t, P, value_conv>().wrap(m, iter_name); } typedef iterator_wrapper<iterator_t, P, value_conv> iter_wrap; }; -#define WRAP_VECTOR(t, conv) vector_wrapper<t, return_value_policy<return_by_value>, conv>().wrap(#t, #t "Iterator") +#define WRAP_VECTOR(m, t, conv) vector_wrapper<t, py::return_value_policy::copy, conv>().wrap(m, #t, #t "Iterator") /* Wrapper for a pair, allows accessing either using C++-style members (.first and @@ -189,58 +184,55 @@ template <typename T1, typename T2> struct pair_wrapper struct pair_iterator_wrapper { - static object next(std::pair<T &, int> &iter) + static py::object next(std::pair<T &, int> &iter) { if (iter.second == 0) { iter.second++; - return object(iter.first.first); + return py::cast(iter.first.first); } else if (iter.second == 1) { iter.second++; - return object(iter.first.second); + return py::cast(iter.first.second); } 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"); + throw py::error_already_set(); } } - static void wrap(const char *python_name) + static void wrap(py::module &m, const char *python_name) { - class_<std::pair<T &, int>>(python_name, no_init).def("__next__", next); + py::class_<std::pair<T &, int>>(m, python_name).def("__next__", next); } }; - static object get(T &x, int i) + static py::object get(T &x, int i) { if ((i >= 2) || (i < 0)) KeyError(); - return (i == 1) ? object(x.second) : object(x.first); + return (i == 1) ? py::object(x.second) : py::object(x.first); } - static void set(T &x, int i, object val) + static void set(T &x, int i, py::object val) { if ((i >= 2) || (i < 0)) KeyError(); if (i == 0) - x.first = extract<T1>(val); + x.first = val.cast<T1>(); if (i == 1) - x.second = extract<T2>(val); + x.second = val.cast<T2>(); } static int len(T &x) { return 2; } static std::pair<T &, int> iter(T &x) { return std::make_pair(boost::ref(x), 0); }; - static void wrap(const char *pair_name, const char *iter_name) + static void wrap(py::module &m, const char *pair_name, const char *iter_name) { - pair_iterator_wrapper::wrap(iter_name); - class_<T>(pair_name, no_init) + pair_iterator_wrapper::wrap(m, iter_name); + py::class_<T>(m, pair_name) .def("__iter__", iter) .def("__len__", len) .def("__getitem__", get) - .def("__setitem__", set, with_custodian_and_ward<1, 2>()) + .def("__setitem__", set, py::keep_alive<1, 2>()) .def_readwrite("first", &T::first) .def_readwrite("second", &T::second); } @@ -257,36 +249,34 @@ template <typename T1, typename T2, typename value_conv> struct map_pair_wrapper struct pair_iterator_wrapper { - static object next(std::pair<wrapped_pair &, int> &iter) + static py::object next(std::pair<wrapped_pair &, int> &iter) { if (iter.second == 0) { iter.second++; - return object(PythonConversion::string_converter<decltype(iter.first.base.first)>().to_str( + return py::cast(PythonConversion::string_converter<decltype(iter.first.base.first)>().to_str( iter.first.ctx, iter.first.base.first)); } else if (iter.second == 1) { iter.second++; - return object(value_conv()(iter.first.ctx, iter.first.base.second)); + return py::cast(value_conv()(iter.first.ctx, iter.first.base.second)); } 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"); + throw py::error_already_set(); } } - static void wrap(const char *python_name) + static void wrap(py::module &m, const char *python_name) { - class_<std::pair<wrapped_pair &, int>>(python_name, no_init).def("__next__", next); + //FIXME + //py::class_<std::pair<wrapped_pair &, int>>(m, python_name).def("__next__", next); } }; - static object get(wrapped_pair &x, int i) + static py::object get(wrapped_pair &x, int i) { if ((i >= 2) || (i < 0)) KeyError(); - return (i == 1) ? object(value_conv()(x.ctx, x.base.second)) - : object(PythonConversion::string_converter<decltype(x.base.first)>().to_str(x.ctx, + return (i == 1) ? py::cast(value_conv()(x.ctx, x.base.second)) + : py::cast(PythonConversion::string_converter<decltype(x.base.first)>().to_str(x.ctx, x.base.first)); } @@ -301,15 +291,15 @@ template <typename T1, typename T2, typename value_conv> struct map_pair_wrapper static typename value_conv::ret_type second_getter(wrapped_pair &t) { return value_conv()(t.ctx, t.base.second); } - static void wrap(const char *pair_name, const char *iter_name) + static void wrap(py::module &m, const char *pair_name, const char *iter_name) { - pair_iterator_wrapper::wrap(iter_name); - class_<wrapped_pair>(pair_name, no_init) + pair_iterator_wrapper::wrap(m, iter_name); + py::class_<wrapped_pair>(m, pair_name) .def("__iter__", iter) .def("__len__", len) .def("__getitem__", get) - .add_property("first", first_getter) - .add_property("second", second_getter); + .def_property_readonly("first", first_getter) + .def_property_readonly("second", second_getter); } }; @@ -358,17 +348,17 @@ template <typename T, typename value_conv> struct map_wrapper return x.base.count(k); } - static void wrap(const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) + static void wrap(py::module &m, const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) { - map_pair_wrapper<typename KV::first_type, typename KV::second_type, value_conv>::wrap(kv_name, kv_iter_name); - typedef range_wrapper<T &, return_value_policy<return_by_value>, PythonConversion::wrap_context<KV &>> rw; - typename rw::iter_wrap().wrap(iter_name); - class_<wrapped_map>(map_name, no_init) + map_pair_wrapper<typename KV::first_type, typename KV::second_type, value_conv>::wrap(m, kv_name, kv_iter_name); + typedef range_wrapper<T &, py::return_value_policy::copy, PythonConversion::wrap_context<KV &>> rw; + typename rw::iter_wrap().wrap(m, iter_name); + py::class_<wrapped_map>(m, map_name) .def("__iter__", rw::iter) .def("__len__", len) .def("__contains__", contains) .def("__getitem__", get) - .def("__setitem__", set, with_custodian_and_ward<1, 2>()); + .def("__setitem__", set, py::keep_alive<1, 2>()); } }; @@ -383,36 +373,34 @@ template <typename T1, typename T2> struct map_pair_wrapper_uptr struct pair_iterator_wrapper { - static object next(std::pair<wrapped_pair &, int> &iter) + static py::object next(std::pair<wrapped_pair &, int> &iter) { if (iter.second == 0) { iter.second++; - return object(PythonConversion::string_converter<decltype(iter.first.base.first)>().to_str( + return py::cast(PythonConversion::string_converter<decltype(iter.first.base.first)>().to_str( iter.first.ctx, iter.first.base.first)); } else if (iter.second == 1) { iter.second++; - return object(PythonConversion::ContextualWrapper<V &>(iter.first.ctx, *iter.first.base.second.get())); + return py::cast(PythonConversion::ContextualWrapper<V &>(iter.first.ctx, *iter.first.base.second.get())); } 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"); + throw py::error_already_set(); } } - static void wrap(const char *python_name) + static void wrap(py::module &m, const char *python_name) { - class_<std::pair<wrapped_pair &, int>>(python_name, no_init).def("__next__", next); + //FIXME + //py::class_<std::pair<wrapped_pair &, int>>(m, python_name).def("__next__", next); } }; - static object get(wrapped_pair &x, int i) + static py::object get(wrapped_pair &x, int i) { if ((i >= 2) || (i < 0)) KeyError(); - return (i == 1) ? object(PythonConversion::ContextualWrapper<V &>(x.ctx, *x.base.second.get())) - : object(PythonConversion::string_converter<decltype(x.base.first)>().to_str(x.ctx, + return (i == 1) ? py::cast(PythonConversion::ContextualWrapper<V &>(x.ctx, *x.base.second.get())) + : py::cast(PythonConversion::string_converter<decltype(x.base.first)>().to_str(x.ctx, x.base.first)); } @@ -430,15 +418,15 @@ template <typename T1, typename T2> struct map_pair_wrapper_uptr return PythonConversion::ContextualWrapper<V &>(t.ctx, *t.base.second.get()); } - static void wrap(const char *pair_name, const char *iter_name) + static void wrap(py::module &m, const char *pair_name, const char *iter_name) { - pair_iterator_wrapper::wrap(iter_name); - class_<wrapped_pair>(pair_name, no_init) + pair_iterator_wrapper::wrap(m, iter_name); + py::class_<wrapped_pair>(m, pair_name) .def("__iter__", iter) .def("__len__", len) .def("__getitem__", get) - .add_property("first", first_getter) - .add_property("second", second_getter); + .def_property_readonly("first", first_getter) + .def_property_readonly("second", second_getter); } }; @@ -487,24 +475,24 @@ template <typename T> struct map_wrapper_uptr return x.base.count(k); } - static void wrap(const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) + static void wrap(py::module &m, const char *map_name, const char *kv_name, const char *kv_iter_name, const char *iter_name) { - map_pair_wrapper_uptr<typename KV::first_type, typename KV::second_type>::wrap(kv_name, kv_iter_name); - typedef range_wrapper<T &, return_value_policy<return_by_value>, PythonConversion::wrap_context<KV &>> rw; - typename rw::iter_wrap().wrap(iter_name); - class_<wrapped_map>(map_name, no_init) + map_pair_wrapper_uptr<typename KV::first_type, typename KV::second_type>::wrap(m, kv_name, kv_iter_name); + typedef range_wrapper<T &, py::return_value_policy::copy, PythonConversion::wrap_context<KV &>> rw; + typename rw::iter_wrap().wrap(m, iter_name); + py::class_<wrapped_map>(m, map_name) .def("__iter__", rw::iter) .def("__len__", len) .def("__contains__", contains) .def("__getitem__", get) - .def("__setitem__", set, with_custodian_and_ward<1, 2>()); + .def("__setitem__", set, py::keep_alive<1, 2>()); } }; -#define WRAP_MAP(t, conv, name) \ - map_wrapper<t, conv>().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") -#define WRAP_MAP_UPTR(t, name) \ - map_wrapper_uptr<t>().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") +#define WRAP_MAP(m, t, conv, name) \ + map_wrapper<t, conv>().wrap(m, #name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") +#define WRAP_MAP_UPTR(m, t, name) \ + map_wrapper_uptr<t>().wrap(m, #name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") NEXTPNR_NAMESPACE_END diff --git a/common/pywrappers.h b/common/pywrappers.h index d50af4c3..e55039c0 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -21,19 +21,13 @@ #ifndef PYWRAPPERS_H #define PYWRAPPERS_H -#include <boost/function_types/function_arity.hpp> -#include <boost/function_types/function_type.hpp> -#include <boost/function_types/parameter_types.hpp> -#include <boost/function_types/result_type.hpp> -#include <boost/python.hpp> -#include <boost/python/suite/indexing/map_indexing_suite.hpp> -#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +#include <pybind11/pybind11.h> #include <utility> #include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN -using namespace boost::python; +namespace py = pybind11; namespace PythonConversion { template <typename T> struct ContextualWrapper @@ -155,14 +149,14 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv> struct fn_ using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t; using conv_result_type = typename rv_conv::ret_type; - static object wrapped_fn(class_type &cls) + static py::object wrapped_fn(class_type &cls) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); try { - return object(rv_conv()(ctx, (base.*fn)())); + return py::cast(rv_conv()(ctx, (base.*fn)())); } catch (bad_wrap &) { - return object(); + return py::object(); } } @@ -176,14 +170,14 @@ template <typename Class, typename FuncT, FuncT fn, typename rv_conv, typename a using conv_result_type = typename rv_conv::ret_type; using conv_arg1_type = typename arg1_conv::arg_type; - static object wrapped_fn(class_type &cls, conv_arg1_type arg1) + static py::object wrapped_fn(class_type &cls, conv_arg1_type arg1) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); try { - return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1)))); + return py::cast(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1)))); } catch (bad_wrap &) { - return object(); + return py::object(); } } @@ -199,14 +193,14 @@ struct fn_wrapper_2a using conv_arg1_type = typename arg1_conv::arg_type; using conv_arg2_type = typename arg2_conv::arg_type; - static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2) + static py::object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); try { - return object(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)))); + return py::cast(rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2)))); } catch (bad_wrap &) { - return object(); + return py::object(); } } @@ -224,15 +218,15 @@ struct fn_wrapper_3a using conv_arg2_type = typename arg2_conv::arg_type; using conv_arg3_type = typename arg3_conv::arg_type; - static object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3) + static py::object wrapped_fn(class_type &cls, conv_arg1_type arg1, conv_arg2_type arg2, conv_arg3_type arg3) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); try { - return object( + return py::cast( rv_conv()(ctx, (base.*fn)(arg1_conv()(ctx, arg1), arg2_conv()(ctx, arg2), arg3_conv()(ctx, arg3)))); } catch (bad_wrap &) { - return object(); + return py::object(); } } @@ -268,7 +262,7 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv> struct f template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, Ta a = arg("arg1")) + template <typename WrapCls, typename Ta> static void def_wrap(WrapCls cls_, const char *name, Ta a = py::arg("arg1")) { cls_.def(name, wrapped_fn, a); } @@ -413,20 +407,20 @@ template <typename Class, typename MemT, MemT mem, typename v_conv> struct reado using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t; using conv_val_type = typename v_conv::ret_type; - static object wrapped_getter(class_type &cls) + static py::object wrapped_getter(class_type &cls) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); try { - return object(v_conv()(ctx, (base.*mem))); + return py::cast(v_conv()(ctx, (base.*mem))); } catch (bad_wrap &) { - return object(); + return py::object(); } } template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { - cls_.add_property(name, wrapped_getter); + cls_.def_property_readonly(name, wrapped_getter); } }; @@ -436,14 +430,14 @@ template <typename Class, typename MemT, MemT mem, typename get_conv, typename s using class_type = typename WrapIfNotContext<Class>::maybe_wrapped_t; using conv_val_type = typename get_conv::ret_type; - static object wrapped_getter(class_type &cls) + static py::object wrapped_getter(class_type &cls) { Context *ctx = get_ctx<Class>(cls); Class &base = get_base<Class>(cls); try { - return object(get_conv()(ctx, (base.*mem))); + return py::cast(get_conv()(ctx, (base.*mem))); } catch (bad_wrap &) { - return object(); + return py::object(); } } @@ -458,7 +452,7 @@ template <typename Class, typename MemT, MemT mem, typename get_conv, typename s template <typename WrapCls> static void def_wrap(WrapCls cls_, const char *name) { - cls_.add_property(name, wrapped_getter, wrapped_setter); + cls_.def_property(name, wrapped_getter, wrapped_setter); } }; |