aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorDavid Shah <dave@ds0.me>2020-07-27 13:50:42 +0100
committerGitHub <noreply@github.com>2020-07-27 13:50:42 +0100
commitb39a2a502065ec1407417ffacdac2154385bf80f (patch)
tree3349c93ac87f5758009c53b3e2eb5b9a130cd0d6 /common
parente6991ad5dc79f6118838f091cc05f10d3377eb4a (diff)
parentfe398ab983aee9283f61c288dc98d94542c30332 (diff)
downloadnextpnr-b39a2a502065ec1407417ffacdac2154385bf80f.tar.gz
nextpnr-b39a2a502065ec1407417ffacdac2154385bf80f.tar.bz2
nextpnr-b39a2a502065ec1407417ffacdac2154385bf80f.zip
Merge pull request #477 from YosysHQ/pybind11
Move to pybind11
Diffstat (limited to 'common')
-rw-r--r--common/handle_error.cc32
-rw-r--r--common/pybindings.cc69
-rw-r--r--common/pybindings.h13
-rw-r--r--common/pycontainers.h199
-rw-r--r--common/pywrappers.h73
5 files changed, 188 insertions, 198 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..b6d5e48a 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); }
@@ -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<PortRef &>
{
@@ -90,13 +84,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);
+ py::register_exception<assertion_failure>(m, "PyExc_AssertionError");
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 +99,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 +107,10 @@ 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>(),
+ 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)
@@ -123,13 +118,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 +138,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>(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 +180,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 +193,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 +203,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 +211,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 +234,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 +250,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 +286,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 +316,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..d7429ed0 100644
--- a/common/pybindings.h
+++ b/common/pybindings.h
@@ -22,9 +22,8 @@
#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 <iostream>
+#include <pybind11/pybind11.h>
#include <stdexcept>
#include <utility>
#include "pycontainers.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, py::return_value_policy::reference);
+ 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..dfcf8ab8 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,8 @@ 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,26 +61,34 @@ 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);
}
};
/*
+A pair that doesn't automatically become a tuple
+*/
+template <typename Ta, typename Tb> 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 !=
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 +117,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 +170,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 +196,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(iter_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_<iter_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 iter_pair<T &, int> iter(T &x) { return iter_pair<T &, int>(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,42 +261,42 @@ 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(iter_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);
+ py::class_<iter_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,
- x.base.first));
+ 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));
}
static int len(wrapped_pair &x) { return 2; }
- static std::pair<wrapped_pair &, int> iter(wrapped_pair &x) { return std::make_pair(boost::ref(x), 0); };
+ static iter_pair<wrapped_pair &, int> iter(wrapped_pair &x)
+ {
+ return iter_pair<wrapped_pair &, int>(boost::ref(x), 0);
+ };
static std::string first_getter(wrapped_pair &t)
{
@@ -301,15 +305,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 +362,18 @@ 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,42 +388,43 @@ 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(iter_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);
+ py::class_<iter_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,
- x.base.first));
+ 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));
}
static int len(wrapped_pair &x) { return 2; }
- static std::pair<wrapped_pair &, int> iter(wrapped_pair &x) { return std::make_pair(boost::ref(x), 0); };
+ static iter_pair<wrapped_pair &, int> iter(wrapped_pair &x)
+ {
+ return iter_pair<wrapped_pair &, int>(boost::ref(x), 0);
+ };
static std::string first_getter(wrapped_pair &t)
{
@@ -430,15 +436,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 +493,25 @@ 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..a864d8cf 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,8 @@ 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);
}
@@ -290,9 +285,9 @@ template <typename Class, typename FuncT, FuncT fn, typename arg1_conv, typename
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, const Ta &a)
+ template <typename WrapCls, typename... Ta> static void def_wrap(WrapCls cls_, const char *name, Ta... a)
{
- cls_.def(name, wrapped_fn, a);
+ cls_.def(name, wrapped_fn, a...);
}
};
@@ -314,9 +309,9 @@ struct fn_wrapper_3a_v
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, const Ta &a)
+ template <typename WrapCls, typename... Ta> static void def_wrap(WrapCls cls_, const char *name, Ta... a)
{
- cls_.def(name, wrapped_fn, a);
+ cls_.def(name, wrapped_fn, a...);
}
};
@@ -342,9 +337,9 @@ struct fn_wrapper_4a_v
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, const Ta &a)
+ template <typename WrapCls, typename... Ta> static void def_wrap(WrapCls cls_, const char *name, Ta... a)
{
- cls_.def(name, wrapped_fn, a);
+ cls_.def(name, wrapped_fn, a...);
}
};
@@ -371,9 +366,9 @@ struct fn_wrapper_5a_v
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, const Ta &a)
+ template <typename WrapCls, typename... Ta> static void def_wrap(WrapCls cls_, const char *name, Ta... a)
{
- cls_.def(name, wrapped_fn, a);
+ cls_.def(name, wrapped_fn, a...);
}
};
@@ -401,9 +396,9 @@ struct fn_wrapper_6a_v
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, const Ta &a)
+ template <typename WrapCls, typename... Ta> static void def_wrap(WrapCls cls_, const char *name, Ta... a)
{
- cls_.def(name, wrapped_fn, a);
+ cls_.def(name, wrapped_fn, a...);
}
};
@@ -413,20 +408,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 +431,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 +453,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);
}
};