[C++-sig] Member overloads signature not matching C++ signature

Stefan Seefeld stefan at seefeld.name
Fri Jul 31 17:04:37 CEST 2015


On 30/07/15 12:53 PM, James Maddison wrote:
> 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]),
>             });
>         }
>     };

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.

>
> 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.

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...



More information about the Cplusplus-sig mailing list