aboutsummaryrefslogtreecommitdiffstats
path: root/common/pycontainers.h
diff options
context:
space:
mode:
authorMiodrag Milanovic <mmicko@gmail.com>2020-07-23 18:35:18 +0200
committerMiodrag Milanovic <mmicko@gmail.com>2020-07-23 18:35:18 +0200
commit8f2b707d026597018333ac60e707e5ab78c25a91 (patch)
treeebf5c6490a56269d674a5d1d5357c7b5e2210872 /common/pycontainers.h
parent444e535f000fd7b53dadf6726d5cd29ac34cc75f (diff)
downloadnextpnr-8f2b707d026597018333ac60e707e5ab78c25a91.tar.gz
nextpnr-8f2b707d026597018333ac60e707e5ab78c25a91.tar.bz2
nextpnr-8f2b707d026597018333ac60e707e5ab78c25a91.zip
Initial conversion to pybind11
Diffstat (limited to 'common/pycontainers.h')
-rw-r--r--common/pycontainers.h170
1 files changed, 79 insertions, 91 deletions
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