I have the following C++ code:
struct MyType { int x, y; };
struct A {
std::vector<MyType> get_data();
};
which I want to interface to Python using Boost Python so that it can be used in the following way:
a = A()
ret = a.get_data();
for r in ret:
print('x=%d; y=%d;' % (r['x'], r['y']))
What I have now is a rather naive:
BOOST_PYTHON_MODULE(pyA) {
class_<A>("A").def("get_data", &A::get_data);
}
which gives me, as expected, the following error
TypeError: No to_python (by-value) converter found for C++ type
when I try to call the get_data()
function from the Python code.
I have seen posts on here (such as std::vector to boost::python::list) which describe how to use vector_indexing_suite
to convert a std::vector<T>
to a list
for some types T
(e.g. floats, strings), but I'm not sure how to extend this to deal with my struct -> dict conversion as well. Any help would be greatly appreciated.
In the end I adopted a solution like the following, which I post here in case it is useful to somebody else in the future. This can be improved by adding boost's "readonly" qualifier, but I haven't done so yet.
#include <boost/python.hpp>
using namespace boost::python;
struct Point {
int x, y;
};
using Points = std::vector<Point>;
struct Converter
{
static PyObject* convert(const Points& v)
{
boost::python::list ret;
for (const auto& c : v) {
boost::python::dict *r = new boost::python::dict();
(*r)["x"] = c.x;
(*r)["y"] = c.y;
ret.append(boost::python::object(*r));
}
return boost::python::incref(ret.ptr());
}
};
BOOST_PYTHON_MODULE(mymodule)
{
boost::python::to_python_converter<Points, Converter>();
class_<MyClass, boost::noncopyable>("MyClass")
.def("get_data", &MyClass::get_data);
}