Discussion:
[C++-sig] Member overloads signature not matching C++ signature
James Maddison
2015-07-30 16:53:50 UTC
Permalink
I am trying to bind a C++ class but python is reporting there is no
matching signature for two of the methods which are I am trying to bind
using the member function overloads macro.

The class looks like so:

struct path {
path();
path(double line_width);

void move_to(point_t point);
void line_to(point_t point);
void curve_to(std::array<point_t, 3>&& points)
void curve_to(const std::array<point_t, 3>& points);
void fill(context& ctx, bool close = true) const;
void stroke(context& ctx, bool close = true) const;
};

I'm not sure if this is the best way but I have made a thin wrapper
around the class such that the curve_to method can be called with a tuple:

struct path_wrapper : path {
using path::path;

void curve_to(const py::tuple& points)
{
path::curve_to({
py::extract<path::point_t>(points[0]),
py::extract<path::point_t>(points[1]),
py::extract<path::point_t>(points[2]),
});
}
};

The function overloads are being defined as such:

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(
path_fill_overloads, fill, 1, 2
);

BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(
path_stroke_overloads, stroke, 1, 2
);

I then bind the class as such:

py::class_<path_wrapper>("Path")
.def(py::init<double>())
.def("move_to", &path::move_to)
.def("line_to", &path::line_to)
.def("curve_to", &path_wrapper::curve_to)
.def("fill", &path::fill, path_fill_overloads())
.def("stroke", &path::stroke, path_stroke_overloads());

I am binding the other classes named throughout this process, but I have
omitted their actual class_ calls from this message.

When I make a call to the methods in python I recieve the following error:

Traceback (most recent call last):
File "/home/james/projects/imgen/patterns/triangles.py", line 46,
in draw
path.stroke(context)
Boost.Python.ArgumentError: Python argument types in
Path.stroke(Path, Context)
did not match C++ signature:
stroke(path {lvalue}, context {lvalue})
stroke(path {lvalue}, context {lvalue}, bool)

I am really confused as the signatures appear to match. I suspect I've
broken the converters with my wrapper class but I am unsure how to fix it.

Thank you.
Stefan Seefeld
2015-07-31 15:04:37 UTC
Permalink
Post by James Maddison
I am trying to bind a C++ class but python is reporting there is no
matching signature for two of the methods which are I am trying to
bind using the member function overloads macro.
struct path {
path();
path(double line_width);
void move_to(point_t point);
void line_to(point_t point);
void curve_to(std::array<point_t, 3>&& points)
void curve_to(const std::array<point_t, 3>& points);
void fill(context& ctx, bool close = true) const;
void stroke(context& ctx, bool close = true) const;
};
I'm not sure if this is the best way but I have made a thin wrapper
struct path_wrapper : path {
using path::path;
void curve_to(const py::tuple& points)
{
path::curve_to({
py::extract<path::point_t>(points[0]),
py::extract<path::point_t>(points[1]),
py::extract<path::point_t>(points[2]),
});
}
};
I think this could be simplified a bit: You don't need an entire new
type to wrap a single member function. Just use a free (non-member)
function definition with an additional first argument standing for "this":

void curve_to(path &p, py::tuple const &points)
{
...
}

and then use "curve_to" instead of "&path_wrapper::curve_to" when
binding it.
Post by James Maddison
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(
path_fill_overloads, fill, 1, 2
);
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(
path_stroke_overloads, stroke, 1, 2
);
py::class_<path_wrapper>("Path")
.def(py::init<double>())
.def("move_to", &path::move_to)
.def("line_to", &path::line_to)
.def("curve_to", &path_wrapper::curve_to)
.def("fill", &path::fill, path_fill_overloads())
.def("stroke", &path::stroke, path_stroke_overloads());
I am binding the other classes named throughout this process, but I
have omitted their actual class_ calls from this message.
File "/home/james/projects/imgen/patterns/triangles.py", line
46, in draw
path.stroke(context)
Boost.Python.ArgumentError: Python argument types in
Path.stroke(Path, Context)
stroke(path {lvalue}, context {lvalue})
stroke(path {lvalue}, context {lvalue}, bool)
I am really confused as the signatures appear to match. I suspect I've
broken the converters with my wrapper class but I am unsure how to fix it.
I suspect the problem is that you "context" argument is a non-const
reference. If it were const, the binding would work. If it has to be
non-const, you need to supply a call-policy. (Unfortunately I'm not sure
how to do that with the BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS macro.
But given that you only have two overloads, perhaps you can avoid the
macro alltogether, just to get this working.

Regards,
Stefan
--
...ich hab' noch einen Koffer in Berlin...
Loading...