From 8f2b707d026597018333ac60e707e5ab78c25a91 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 23 Jul 2020 18:35:18 +0200 Subject: Initial conversion to pybind11 --- common/handle_error.cc | 32 ++++------ common/pybindings.cc | 64 ++++++++++--------- common/pybindings.h | 13 ++-- common/pycontainers.h | 170 +++++++++++++++++++++++-------------------------- common/pywrappers.h | 52 +++++++-------- 5 files changed, 154 insertions(+), 177 deletions(-) (limited to 'common') 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 -#include +#include #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 e_type_pstr(type_pstr); + py::object obj = py::reinterpret_borrow(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(obj)) + ret = obj.cast(); 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 returned(a); - if (returned.check()) - ret += ": " + returned(); + py::object obj = py::reinterpret_borrow(value_ptr); + if (py::isinstance(obj)) + ret += ": " + obj.cast(); 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 returned(tb_str); - if (returned.check()) - ret += ": " + returned(); + if (py::isinstance(tb_str)) + ret += ": " + tb_str.cast(); 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 } // namespace PythonConversion -BOOST_PYTHON_MODULE(MODULE_NAME) +PYBIND11_MODULE(MODULE_NAME, m) { - register_exception_translator(&translate_assertfail); + //register_exception_translator(&translate_assertfail); using namespace PythonConversion; - enum_("GraphicElementType") + py::enum_(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_("GraphicElementStyle") + py::enum_(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") - .def(init( - (args("type"), "style", "x1", "y1", "x2", "y2", "z"))) + py::class_(m, "GraphicElement") + .def(py::init( + //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") + py::enum_(m, "PortType") .value("PORT_IN", PORT_IN) .value("PORT_OUT", PORT_OUT) .value("PORT_INOUT", PORT_INOUT) .export_values(); - enum_("PlaceStrength") + py::enum_(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 IdIdMap; typedef std::unordered_map> RegionMap; - class_("BaseCtx", no_init); + py::class_>(m, "BaseCtx"); - auto loc_cls = class_("Loc") - .def(init()) + auto loc_cls = py::class_(m, "Loc") + .def(py::init()) .def_readwrite("x", &Loc::x) .def_readwrite("y", &Loc::y) .def_readwrite("z", &Loc::z); - auto ci_cls = class_>("CellInfo", no_init); + auto ci_cls = py::class_>(m, "CellInfo"); readwrite_wrapper, conv_from_str>::def_wrap(ci_cls, "name"); readwrite_wrapper, @@ -185,7 +187,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) fn_wrapper_1a_v>::def_wrap(ci_cls, "unsetAttr"); - auto pi_cls = class_>("PortInfo", no_init); + auto pi_cls = py::class_>(m, "PortInfo"); readwrite_wrapper, conv_from_str>::def_wrap(pi_cls, "name"); readonly_wrapper>::def_wrap(pi_cls, @@ -198,7 +200,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) typedef std::unordered_set BelSet; typedef std::unordered_set WireSet; - auto ni_cls = class_>("NetInfo", no_init); + auto ni_cls = py::class_>(m, "NetInfo"); readwrite_wrapper, conv_from_str>::def_wrap(ni_cls, "name"); readwrite_wrapper, @@ -208,7 +210,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readonly_wrapper>::def_wrap(ni_cls, "wires"); - auto pr_cls = class_>("PortRef", no_init); + auto pr_cls = py::class_>(m, "PortRef"); readonly_wrapper>::def_wrap(pr_cls, "cell"); readwrite_wrapper, @@ -216,16 +218,16 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readwrite_wrapper, pass_through>::def_wrap(pr_cls, "budget"); - auto pm_cls = class_>("PipMap", no_init); + auto pm_cls = py::class_>(m, "PipMap"); readwrite_wrapper, conv_from_str>::def_wrap(pm_cls, "pip"); readwrite_wrapper, pass_through>::def_wrap(pm_cls, "strength"); - def("parse_json", parse_json_shim); - def("load_design", load_design_shim, return_value_policy()); + m.def("parse_json", parse_json_shim); + m.def("load_design", load_design_shim, py::return_value_policy::take_ownership); - auto region_cls = class_>("Region", no_init); + auto region_cls = py::class_>(m, "Region"); readwrite_wrapper, conv_from_str>::def_wrap(region_cls, "name"); readwrite_wrapper, @@ -239,7 +241,7 @@ BOOST_PYTHON_MODULE(MODULE_NAME) readonly_wrapper>::def_wrap(region_cls, "wires"); - auto hierarchy_cls = class_>("HierarchicalCell", no_init); + auto hierarchy_cls = py::class_>(m, "HierarchicalCell"); readwrite_wrapper, conv_from_str>::def_wrap(hierarchy_cls, "name"); readwrite_wrapper>::def_wrap(hierarchy_cls, "nets"); readonly_wrapper>::def_wrap(hierarchy_cls, "hier_cells"); - WRAP_MAP(AttrMap, conv_to_str, "AttrMap"); - WRAP_MAP(PortMap, wrap_context, "PortMap"); - WRAP_MAP(IdIdMap, conv_to_str, "IdIdMap"); - WRAP_MAP(WireMap, wrap_context, "WireMap"); - WRAP_MAP_UPTR(RegionMap, "RegionMap"); + WRAP_MAP(m, AttrMap, conv_to_str, "AttrMap"); + WRAP_MAP(m, PortMap, wrap_context, "PortMap"); + WRAP_MAP(m, IdIdMap, conv_to_str, "IdIdMap"); + WRAP_MAP(m, WireMap, wrap_context, "WireMap"); + WRAP_MAP_UPTR(m, RegionMap, "RegionMap"); - WRAP_VECTOR(PortRefVector, wrap_context); + WRAP_VECTOR(m, PortRefVector, wrap_context); - 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 -#include -#include -#include +#include #include #include +#include #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 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 -#include -#include +#include #include #include #include @@ -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 containing (current, end), wrapped in a ContextualWrapp */ -template > struct iterator_wrapper +template > struct iterator_wrapper { typedef decltype(*(std::declval())) value_t; @@ -62,16 +60,13 @@ template (python_name, no_init).def("__next__", next, P()); + py::class_(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 , +template > 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_(range_name, no_init).def("__iter__", iter).def("__repr__", repr); - iterator_wrapper().wrap(iter_name); + py::class_(m, range_name).def("__iter__", iter).def("__repr__", repr); + iterator_wrapper().wrap(m, iter_name); } typedef iterator_wrapper iter_wrap; }; -#define WRAP_RANGE(t, conv) \ - range_wrapper, conv>().wrap(#t "Range", #t "Iterator") +#define WRAP_RANGE(m, t, conv) \ + range_wrapper().wrap(m, #t "Range", #t "Iterator") /* A wrapper for a vector or similar structure. With support for conversion */ -template , +template > 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_(range_name, no_init) + py::class_(m, range_name) .def("__iter__", iter) .def("__repr__", repr) .def("__len__", len) .def("__getitem__", getitem); - iterator_wrapper().wrap(iter_name); + iterator_wrapper().wrap(m, iter_name); } typedef iterator_wrapper iter_wrap; }; -#define WRAP_VECTOR(t, conv) vector_wrapper, conv>().wrap(#t, #t "Iterator") +#define WRAP_VECTOR(m, t, conv) vector_wrapper().wrap(m, #t, #t "Iterator") /* Wrapper for a pair, allows accessing either using C++-style members (.first and @@ -189,58 +184,55 @@ template struct pair_wrapper struct pair_iterator_wrapper { - static object next(std::pair &iter) + static py::object next(std::pair &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_>(python_name, no_init).def("__next__", next); + py::class_>(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(val); + x.first = val.cast(); if (i == 1) - x.second = extract(val); + x.second = val.cast(); } static int len(T &x) { return 2; } static std::pair 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_(pair_name, no_init) + pair_iterator_wrapper::wrap(m, iter_name); + py::class_(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 struct map_pair_wrapper struct pair_iterator_wrapper { - static object next(std::pair &iter) + static py::object next(std::pair &iter) { if (iter.second == 0) { iter.second++; - return object(PythonConversion::string_converter().to_str( + return py::cast(PythonConversion::string_converter().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_>(python_name, no_init).def("__next__", next); + //FIXME + //py::class_>(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().to_str(x.ctx, + return (i == 1) ? py::cast(value_conv()(x.ctx, x.base.second)) + : py::cast(PythonConversion::string_converter().to_str(x.ctx, x.base.first)); } @@ -301,15 +291,15 @@ template 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_(pair_name, no_init) + pair_iterator_wrapper::wrap(m, iter_name); + py::class_(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 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::wrap(kv_name, kv_iter_name); - typedef range_wrapper, PythonConversion::wrap_context> rw; - typename rw::iter_wrap().wrap(iter_name); - class_(map_name, no_init) + map_pair_wrapper::wrap(m, kv_name, kv_iter_name); + typedef range_wrapper> rw; + typename rw::iter_wrap().wrap(m, iter_name); + py::class_(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 struct map_pair_wrapper_uptr struct pair_iterator_wrapper { - static object next(std::pair &iter) + static py::object next(std::pair &iter) { if (iter.second == 0) { iter.second++; - return object(PythonConversion::string_converter().to_str( + return py::cast(PythonConversion::string_converter().to_str( iter.first.ctx, iter.first.base.first)); } else if (iter.second == 1) { iter.second++; - return object(PythonConversion::ContextualWrapper(iter.first.ctx, *iter.first.base.second.get())); + return py::cast(PythonConversion::ContextualWrapper(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_>(python_name, no_init).def("__next__", next); + //FIXME + //py::class_>(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(x.ctx, *x.base.second.get())) - : object(PythonConversion::string_converter().to_str(x.ctx, + return (i == 1) ? py::cast(PythonConversion::ContextualWrapper(x.ctx, *x.base.second.get())) + : py::cast(PythonConversion::string_converter().to_str(x.ctx, x.base.first)); } @@ -430,15 +418,15 @@ template struct map_pair_wrapper_uptr return PythonConversion::ContextualWrapper(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_(pair_name, no_init) + pair_iterator_wrapper::wrap(m, iter_name); + py::class_(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 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::wrap(kv_name, kv_iter_name); - typedef range_wrapper, PythonConversion::wrap_context> rw; - typename rw::iter_wrap().wrap(iter_name); - class_(map_name, no_init) + map_pair_wrapper_uptr::wrap(m, kv_name, kv_iter_name); + typedef range_wrapper> rw; + typename rw::iter_wrap().wrap(m, iter_name); + py::class_(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().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") -#define WRAP_MAP_UPTR(t, name) \ - map_wrapper_uptr().wrap(#name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") +#define WRAP_MAP(m, t, conv, name) \ + map_wrapper().wrap(m, #name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") +#define WRAP_MAP_UPTR(m, t, name) \ + map_wrapper_uptr().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 -#include -#include -#include -#include -#include -#include +#include #include #include "nextpnr.h" NEXTPNR_NAMESPACE_BEGIN -using namespace boost::python; +namespace py = pybind11; namespace PythonConversion { template struct ContextualWrapper @@ -155,14 +149,14 @@ template struct fn_ using class_type = typename WrapIfNotContext::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(cls); Class &base = get_base(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 (cls); Class &base = get_base(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(cls); Class &base = get_base(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(cls); Class &base = get_base(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 struct f template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template static void def_wrap(WrapCls cls_, const char *name, Ta a = arg("arg1")) + template 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 struct reado using class_type = typename WrapIfNotContext::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(cls); Class &base = get_base(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 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 ::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(cls); Class &base = get_base(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 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); } }; -- cgit v1.2.3 From cca7d3aef7e97228bddc04601e5c6f1d03894be9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 23 Jul 2020 19:55:25 +0200 Subject: possible fix --- common/pycontainers.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'common') diff --git a/common/pycontainers.h b/common/pycontainers.h index 15e502d1..0a5092a3 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -249,7 +249,7 @@ template struct map_pair_wrapper struct pair_iterator_wrapper { - static py::object next(std::pair &iter) + static py::object next(std::pair &&iter) { if (iter.second == 0) { iter.second++; @@ -266,8 +266,7 @@ template struct map_pair_wrapper static void wrap(py::module &m, const char *python_name) { - //FIXME - //py::class_>(m, python_name).def("__next__", next); + py::class_>(m, python_name).def("__next__", next); } }; @@ -373,7 +372,7 @@ template struct map_pair_wrapper_uptr struct pair_iterator_wrapper { - static py::object next(std::pair &iter) + static py::object next(std::pair &&iter) { if (iter.second == 0) { iter.second++; @@ -390,8 +389,7 @@ template struct map_pair_wrapper_uptr static void wrap(py::module &m, const char *python_name) { - //FIXME - //py::class_>(m, python_name).def("__next__", next); + py::class_>(m, python_name).def("__next__", next); } }; -- cgit v1.2.3 From 8a90328ab7e1958d5e33f2961ad65c35682d9ce6 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Thu, 23 Jul 2020 20:20:26 +0200 Subject: proper ctx export --- common/pybindings.cc | 2 +- common/pybindings.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 49acb996..e1a7d313 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -145,7 +145,7 @@ PYBIND11_MODULE(MODULE_NAME, m) typedef std::unordered_map IdIdMap; typedef std::unordered_map> RegionMap; - py::class_>(m, "BaseCtx"); + py::class_(m, "BaseCtx"); auto loc_cls = py::class_(m, "Loc") .def(py::init()) diff --git a/common/pybindings.h b/common/pybindings.h index 4923c821..e143ddf4 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -45,7 +45,7 @@ template void python_export_global(const char *name, Tn &x) return; d = PyModule_GetDict(m); try { - py::object obj = py::cast(x); + py::object obj = py::cast(x, py::return_value_policy::reference); PyDict_SetItemString(d, name, obj.ptr()); } catch (py::error_already_set const &) { // Parse and output the exception -- cgit v1.2.3 From 770bb40eb3dc2f5b8581dad1d750463b7a6963e7 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 24 Jul 2020 10:47:10 +0200 Subject: proper argument propagation --- common/pywrappers.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'common') diff --git a/common/pywrappers.h b/common/pywrappers.h index e55039c0..bb94120c 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -284,9 +284,9 @@ template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + template static void def_wrap(WrapCls cls_, const char *name, Ta... a) { - cls_.def(name, wrapped_fn, a); + cls_.def(name, wrapped_fn, a...); } }; @@ -308,9 +308,9 @@ struct fn_wrapper_3a_v template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + template static void def_wrap(WrapCls cls_, const char *name, Ta... a) { - cls_.def(name, wrapped_fn, a); + cls_.def(name, wrapped_fn, a...); } }; @@ -336,9 +336,9 @@ struct fn_wrapper_4a_v template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + template static void def_wrap(WrapCls cls_, const char *name, Ta... a) { - cls_.def(name, wrapped_fn, a); + cls_.def(name, wrapped_fn, a...); } }; @@ -365,9 +365,9 @@ struct fn_wrapper_5a_v template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + template static void def_wrap(WrapCls cls_, const char *name, Ta... a) { - cls_.def(name, wrapped_fn, a); + cls_.def(name, wrapped_fn, a...); } }; @@ -395,9 +395,9 @@ struct fn_wrapper_6a_v template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template static void def_wrap(WrapCls cls_, const char *name, const Ta &a) + template static void def_wrap(WrapCls cls_, const char *name, Ta... a) { - cls_.def(name, wrapped_fn, a); + cls_.def(name, wrapped_fn, a...); } }; -- cgit v1.2.3 From 598ef014e686a1c03821b6728782dbf98f8ff038 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 24 Jul 2020 10:59:11 +0200 Subject: Fixed named arguments --- common/pybindings.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index e1a7d313..3f288e78 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -114,10 +114,9 @@ PYBIND11_MODULE(MODULE_NAME, m) .export_values(); py::class_(m, "GraphicElement") - .def(py::init( - //FIXME - //(args("type"), "style", "x1", "y1", "x2", "y2", "z") - )) + .def(py::init(), + py::arg("type"), py::arg("style"), py::arg("x1"), py::arg("y1"), py::arg("x2"), py::arg("y2"), py::arg("z") + ) .def_readwrite("type", &GraphicElement::type) .def_readwrite("x1", &GraphicElement::x1) .def_readwrite("y1", &GraphicElement::y1) -- cgit v1.2.3 From 597f4a1495a7e6b4bd5eed426cd2808d77280fd9 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Fri, 24 Jul 2020 11:03:08 +0200 Subject: exception translation --- common/pybindings.cc | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 3f288e78..4711f10c 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -64,12 +64,6 @@ Context *load_design_shim(std::string filename, ArchArgs args) return d; } -void translate_assertfail(const assertion_failure &e) -{ - // Use the Python 'C' API to set up an exception object - PyErr_SetString(PyExc_AssertionError, e.what()); -} - namespace PythonConversion { template <> struct string_converter { @@ -92,7 +86,7 @@ template <> struct string_converter PYBIND11_MODULE(MODULE_NAME, m) { - //register_exception_translator(&translate_assertfail); + py::register_exception(m, "PyExc_AssertionError"); using namespace PythonConversion; -- cgit v1.2.3 From bb6e6a15f1f1a061f4b59c3eddd3430d57681c6d Mon Sep 17 00:00:00 2001 From: David Shah Date: Fri, 24 Jul 2020 16:27:47 +0100 Subject: pycontainers: Fix kv-pair-iter type Signed-off-by: David Shah --- common/pycontainers.h | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'common') diff --git a/common/pycontainers.h b/common/pycontainers.h index 0a5092a3..d0d7d92a 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -70,6 +70,16 @@ template struct iter_pair { + iter_pair() {}; + iter_pair(const Ta &first, const Tb &second) : first(first), second(second) {}; + Ta first; + Tb second; +}; + /* A wrapper for a nextpnr Range. Ranges should have two functions, begin() and end() which return iterator-like objects supporting ++, * and != @@ -184,7 +194,7 @@ template struct pair_wrapper struct pair_iterator_wrapper { - static py::object next(std::pair &iter) + static py::object next(iter_pair &iter) { if (iter.second == 0) { iter.second++; @@ -200,7 +210,7 @@ template struct pair_wrapper static void wrap(py::module &m, const char *python_name) { - py::class_>(m, python_name).def("__next__", next); + py::class_>(m, python_name).def("__next__", next); } }; @@ -223,7 +233,7 @@ template struct pair_wrapper static int len(T &x) { return 2; } - static std::pair iter(T &x) { return std::make_pair(boost::ref(x), 0); }; + static iter_pair iter(T &x) { return iter_pair(boost::ref(x), 0); }; static void wrap(py::module &m, const char *pair_name, const char *iter_name) { @@ -249,7 +259,7 @@ template struct map_pair_wrapper struct pair_iterator_wrapper { - static py::object next(std::pair &&iter) + static py::object next(iter_pair &iter) { if (iter.second == 0) { iter.second++; @@ -266,7 +276,7 @@ template struct map_pair_wrapper static void wrap(py::module &m, const char *python_name) { - py::class_>(m, python_name).def("__next__", next); + py::class_>(m, python_name).def("__next__", next); } }; @@ -281,7 +291,7 @@ template struct map_pair_wrapper static int len(wrapped_pair &x) { return 2; } - static std::pair iter(wrapped_pair &x) { return std::make_pair(boost::ref(x), 0); }; + static iter_pair iter(wrapped_pair &x) { return iter_pair(boost::ref(x), 0); }; static std::string first_getter(wrapped_pair &t) { @@ -372,7 +382,7 @@ template struct map_pair_wrapper_uptr struct pair_iterator_wrapper { - static py::object next(std::pair &&iter) + static py::object next(iter_pair &iter) { if (iter.second == 0) { iter.second++; @@ -389,7 +399,7 @@ template struct map_pair_wrapper_uptr static void wrap(py::module &m, const char *python_name) { - py::class_>(m, python_name).def("__next__", next); + py::class_>(m, python_name).def("__next__", next); } }; @@ -404,7 +414,7 @@ template struct map_pair_wrapper_uptr static int len(wrapped_pair &x) { return 2; } - static std::pair iter(wrapped_pair &x) { return std::make_pair(boost::ref(x), 0); }; + static iter_pair iter(wrapped_pair &x) { return iter_pair(boost::ref(x), 0); }; static std::string first_getter(wrapped_pair &t) { -- cgit v1.2.3 From fe398ab983aee9283f61c288dc98d94542c30332 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 25 Jul 2020 10:17:13 +0200 Subject: clangformat --- common/pybindings.cc | 4 ++-- common/pybindings.h | 2 +- common/pycontainers.h | 41 ++++++++++++++++++++++++++--------------- common/pywrappers.h | 3 ++- 4 files changed, 31 insertions(+), 19 deletions(-) (limited to 'common') diff --git a/common/pybindings.cc b/common/pybindings.cc index 4711f10c..b6d5e48a 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -109,8 +109,8 @@ PYBIND11_MODULE(MODULE_NAME, m) py::class_(m, "GraphicElement") .def(py::init(), - py::arg("type"), py::arg("style"), py::arg("x1"), py::arg("y1"), py::arg("x2"), py::arg("y2"), py::arg("z") - ) + py::arg("type"), py::arg("style"), py::arg("x1"), py::arg("y1"), py::arg("x2"), py::arg("y2"), + py::arg("z")) .def_readwrite("type", &GraphicElement::type) .def_readwrite("x1", &GraphicElement::x1) .def_readwrite("y1", &GraphicElement::y1) diff --git a/common/pybindings.h b/common/pybindings.h index e143ddf4..d7429ed0 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -22,10 +22,10 @@ #define COMMON_PYBINDINGS_H #include +#include #include #include #include -#include #include "pycontainers.h" #include "pywrappers.h" diff --git a/common/pycontainers.h b/common/pycontainers.h index d0d7d92a..dfcf8ab8 100644 --- a/common/pycontainers.h +++ b/common/pycontainers.h @@ -45,7 +45,8 @@ pair containing (current, end), wrapped in a ContextualWrapp */ -template > struct iterator_wrapper +template > +struct iterator_wrapper { typedef decltype(*(std::declval())) value_t; @@ -73,9 +74,10 @@ template struct iter_pair { - iter_pair() {}; - iter_pair(const Ta &first, const Tb &second) : first(first), second(second) {}; +template struct iter_pair +{ + iter_pair(){}; + iter_pair(const Ta &first, const Tb &second) : first(first), second(second){}; Ta first; Tb second; }; @@ -117,14 +119,14 @@ struct range_wrapper static void wrap(py::module &m, const char *range_name, const char *iter_name) { - py::class_(m, range_name).def("__iter__", iter).def("__repr__", repr); + py::class_(m, range_name).def("__iter__", iter).def("__repr__", repr); iterator_wrapper().wrap(m, iter_name); } typedef iterator_wrapper iter_wrap; }; -#define WRAP_RANGE(m, t, conv) \ +#define WRAP_RANGE(m, t, conv) \ range_wrapper().wrap(m, #t "Range", #t "Iterator") /* @@ -286,12 +288,15 @@ template struct map_pair_wrapper KeyError(); return (i == 1) ? py::cast(value_conv()(x.ctx, x.base.second)) : py::cast(PythonConversion::string_converter().to_str(x.ctx, - x.base.first)); + x.base.first)); } static int len(wrapped_pair &x) { return 2; } - static iter_pair iter(wrapped_pair &x) { return iter_pair(boost::ref(x), 0); }; + static iter_pair iter(wrapped_pair &x) + { + return iter_pair(boost::ref(x), 0); + }; static std::string first_getter(wrapped_pair &t) { @@ -357,7 +362,8 @@ template struct map_wrapper return x.base.count(k); } - static void wrap(py::module &m, 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::wrap(m, kv_name, kv_iter_name); typedef range_wrapper> rw; @@ -390,7 +396,8 @@ template struct map_pair_wrapper_uptr iter.first.ctx, iter.first.base.first)); } else if (iter.second == 1) { iter.second++; - return py::cast(PythonConversion::ContextualWrapper(iter.first.ctx, *iter.first.base.second.get())); + return py::cast( + PythonConversion::ContextualWrapper(iter.first.ctx, *iter.first.base.second.get())); } else { PyErr_SetString(PyExc_StopIteration, "End of range reached"); throw py::error_already_set(); @@ -409,12 +416,15 @@ template struct map_pair_wrapper_uptr KeyError(); return (i == 1) ? py::cast(PythonConversion::ContextualWrapper(x.ctx, *x.base.second.get())) : py::cast(PythonConversion::string_converter().to_str(x.ctx, - x.base.first)); + x.base.first)); } static int len(wrapped_pair &x) { return 2; } - static iter_pair iter(wrapped_pair &x) { return iter_pair(boost::ref(x), 0); }; + static iter_pair iter(wrapped_pair &x) + { + return iter_pair(boost::ref(x), 0); + }; static std::string first_getter(wrapped_pair &t) { @@ -483,7 +493,8 @@ template struct map_wrapper_uptr return x.base.count(k); } - static void wrap(py::module &m, 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::wrap(m, kv_name, kv_iter_name); typedef range_wrapper> rw; @@ -497,9 +508,9 @@ template struct map_wrapper_uptr } }; -#define WRAP_MAP(m, t, conv, name) \ +#define WRAP_MAP(m, t, conv, name) \ map_wrapper().wrap(m, #name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") -#define WRAP_MAP_UPTR(m, t, name) \ +#define WRAP_MAP_UPTR(m, t, name) \ map_wrapper_uptr().wrap(m, #name, #name "KeyValue", #name "KeyValueIter", #name "Iterator") NEXTPNR_NAMESPACE_END diff --git a/common/pywrappers.h b/common/pywrappers.h index bb94120c..a864d8cf 100644 --- a/common/pywrappers.h +++ b/common/pywrappers.h @@ -262,7 +262,8 @@ template struct f template static void def_wrap(WrapCls cls_, const char *name) { cls_.def(name, wrapped_fn); } - template static void def_wrap(WrapCls cls_, const char *name, Ta a = py::arg("arg1")) + template + static void def_wrap(WrapCls cls_, const char *name, Ta a = py::arg("arg1")) { cls_.def(name, wrapped_fn, a); } -- cgit v1.2.3