Pybind11: TypeError: function(): incompatible function arguments with std::vector<std::vector<>>

Created on 4 Sep 2017  路  6Comments  路  Source: pybind/pybind11

Hi,
I have an issue with binding a function with an std::vector<std::vector<double>> argument.
It doesn't seem the conversion is automatically handled.
here is the error:

TypeError: function(): incompatible function arguments. The following argument types are supported:
    1. (self: libcmas.City, arg0: std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, arg1: unicode) -> int

Invoked with: <libcmas.City object at 0x7fa11f6e7730>, [], 'home'

Python code

import libcmas as cmas
city  = cmas.create(filename)
locations=[ ]
homes = city.function(locations, "home") 

CPP code

class City
{
public:
        static City* Create(const std::string& file);
    virtual ~City()=default;
    virtual int function(std::vector<std::vector<double>>& locations, const std::string& type) = 0;

protected:
    City()=default;
};

class PyCity : public City
{
public:
    int function(std::vector<std::vector<double>>& locations, const std::string& type) override
            { PYBIND11_OVERLOAD_PURE(int, City, function, locations, type); }
};

PYBIND11_MODULE(libcmas, m)
{
    py::class_<City, PyCity> city(m, "City");
    city
        .def(py::init<>())
        .def("function", &City::function);

    m.def("create", &City::Create);
}

Most helpful comment

Yes: locations = MyVector([]) and then it can be passed to functions and mutated if passed by non-const reference. The docs are a bit incomplete here. This should be explained better in STL bindings section.

All 6 comments

The example code is incomplete (doesn't compile/run). For automatic conversion of STL containers make sure to #include <pybind11/stl.h>. Also, be aware of this FAQ entry. If that doesn't solve the issue, please post a complete code example.

Adding #include <pybind11/stl.h> solved the error.

However, the referenced argument std::vector<std::vector<double>>& locations is empty on the python side. I have searched the doc and apparently this is due to the fact that pyBind11 is performing a copy even on references. So, I made the type opaque with:
PYBIND11_MAKE_OPAQUE(std::vector<std::vector<double>>);

But the error reappears. Do I have to create a corresponding class_ declaration to associate the opaque type with a name in Python ?
Thx.

Yes, but there's a convenient py::bind_vector function which does most of the binding automatically.

Thanks. So, do I have to declare the locations python variable with the type specified in the py::bind_vector function ? Because it doesn't accept python a list

Yes: locations = MyVector([]) and then it can be passed to functions and mutated if passed by non-const reference. The docs are a bit incomplete here. This should be explained better in STL bindings section.

WORKS!! I love pybind11 !

Was this page helpful?
0 / 5 - 0 ratings