passing pointer to C++ from python using pybind11

瘦欲@ 提交于 2019-12-08 22:05:27

问题


I have created the following class using pybind11:

py::class_<Raster>(m, "Raster")
        .def(py::init<double*, std::size_t, std::size_t, std::size_t, double, double, double>());

However I have no idea how I would call this constructor in Python.. I see that Python expects a float in the place of the double*, but I cannot seem to call it.

I have tried, ctypes.data_as(ctypes.POINTER(ctypes.c_double)) but this does not work...

Edit:

I have distilled the answer from @Sergei answer.

py::class_<Raster>(m, "Raster", py::buffer_protocol())
    .def("__init__", [](Raster& raster, py::array_t<double> buffer, double spacingX, double spacingY, double spacingZ) {
    py::buffer_info info = buffer.request();
    new (&raster) Raster3D(static_cast<double*>(info.ptr), info.shape[0], info.shape[1], info.shape[2], spacingX, spacingY, spacingZ);
    })

回答1:


Pybind does automatic conversions. When you bind f(double *) the argument is assumed to be a pointer to a singe value, not a pointer to the array begin, because it would be quite unnatural to expect such input from python side. So pybind will convert argument using this logic.

If you need to pass raw array to c++ use py::buffer like here:

py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
    .def("__init__", [](Matrix &m, py::buffer b) {
        typedef Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic> Strides;

        /* Request a buffer descriptor from Python */
        py::buffer_info info = b.request();

        /* Some sanity checks ... */
        if (info.format != py::format_descriptor<Scalar>::format())
            throw std::runtime_error("Incompatible format: expected a double array!");

        if (info.ndim != 2)
            throw std::runtime_error("Incompatible buffer dimension!");

        auto strides = Strides(
            info.strides[rowMajor ? 0 : 1] / (py::ssize_t)sizeof(Scalar),
            info.strides[rowMajor ? 1 : 0] / (py::ssize_t)sizeof(Scalar));

        auto map = Eigen::Map<Matrix, 0, Strides>(
            static_cast<Scalar *>(info.ptr), info.shape[0], info.shape[1], strides);

        new (&m) Matrix(map);
    });

To make it work you need to pass a type which follows python buffer protocol.



来源:https://stackoverflow.com/questions/57990269/passing-pointer-to-c-from-python-using-pybind11

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!