Pybind11: How to wrap void functions which take double*

Created on 24 Apr 2018  路  4Comments  路  Source: pybind/pybind11

Hello, I have C++ code with several C-style functions which look like this:

void some_function(double* array, int array_size) { do something with array }

What's the easiest way to wrap these functions? I thought about casting the Python list/numpy array directly to a an array in C++ allocated with new double[array_size] an then calling some_function but I'm
not sure how to do that.

Most helpful comment

The "something obvious" is the fact that in order to call a member function, you need a reference to 'this', so the lambda you define also needs to take a corresponding parameter:

        .def("some_member_function", [](some_class& self, std::vector<double> array) {
            return self.some_member_function(...);
        });

All 4 comments

The easiest approach is probably to bind an intermediate wrapper taking a std::vector and passing its data to the real function:

#include <pybind11/stl.h>
// ...
    m.def("some_function", [](std::vector<double> array) {
        return some_function(array.data(), array.size());
    });

Thanks a lot, this works for me when the function is not defined in a class, however, when some_function is a member of a class, I get an error about incompatible arguments.

Here's a minimal example which reproduces the issue for me:

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

class some_class {
    double class_member; 
};

void some_function(double* array, int array_size) {
    array[0] = 2.;
}

namespace py = pybind11;

PYBIND11_MODULE(example_module, m) {
    m.def("some_function", [](std::vector<double> array) {
            return some_function(array.data(), array.size());
        });

    py::class_<some_class>(m, "some_class")
        .def(py::init())
        .def("some_member_function", [](std::vector<double> array) {
            return 0.;
        });
}

Calling the functions in python results in:

In [2]: import example_module as m

In [3]: m.some_function([0.1, 0.5])

In [4]: instance = m.some_class()

In [5]: instance.some_member_function([0.1, 0.5])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-38c8de031c83> in <module>()
----> 1 instance.some_member_function([0.1, 0.5])

TypeError: some_member_function(): incompatible function arguments. The following argument types are supported:
    1. (self: List[float]) -> float

Invoked with: <example_module.some_class object at 0x1467438e0110>, [0.1, 0.5]

In [6]:
   fread(ESPLout, sizeof(double), rsize * zsize, f);

I'm not very good at C++ so I might be missing something obvious.

The "something obvious" is the fact that in order to call a member function, you need a reference to 'this', so the lambda you define also needs to take a corresponding parameter:

        .def("some_member_function", [](some_class& self, std::vector<double> array) {
            return self.some_member_function(...);
        });

Thank you so much!

Was this page helpful?
0 / 5 - 0 ratings