Closed
Description
When exposing a derived class that inherits from a base class that implements the buffer protocol, using this protocol fails.
Take for example an extended version of the code in the documentation:
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
class Matrix {
public:
Matrix(size_t rows, size_t cols) : m_rows(rows), m_cols(cols) {
m_data = new float[rows*cols];
}
float *data() { return m_data; }
size_t rows() const { return m_rows; }
size_t cols() const { return m_cols; }
private:
size_t m_rows, m_cols;
float *m_data;
};
class SquareMatrix : public Matrix {
public:
SquareMatrix(size_t n) : Matrix(n, n) {}
};
namespace py = pybind11;
PYBIND11_PLUGIN(test) {
py::module m("test");
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
.def(py::init<size_t, size_t>())
.def_buffer([](Matrix &m) -> py::buffer_info {
return py::buffer_info(m.data(), sizeof(float), py::format_descriptor<float>::format(), 2, { m.rows(), m.cols() }, { sizeof(float) * m.rows(), sizeof(float) });
});
py::class_<SquareMatrix, Matrix>(m, "SquareMatrix")
.def(py::init<size_t>());
return m.ptr();
}
Using this code results in the following:
>>> import test
>>> import numpy as np
>>> np.asarray(test.Matrix(4,5))
array([[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 1.51019586e+11],
[ 1.51019586e+11, 4.56150676e-41, 1.32649094e+20,
4.56150676e-41, 1.11956001e+11],
[ 1.11956001e+11, 4.56150676e-41, 1.32648531e+20,
4.56150676e-41, 1.52991748e-38],
[ 1.52991748e-38, 0.00000000e+00, 0.00000000e+00,
0.00000000e+00, 1.27985124e+20]], dtype=float32)
>>> np.asarray(test.SquareMatrix(4))
array(<test.SquareMatrix object at 0x7f2860e198d0>, dtype=object)
>>> memoryview(test.SquareMatrix(4))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
BufferError: generic_type::getbuffer(): Internal error
As far as I can see, the problem is that Python knóws that the type implements the buffer protocol (because of the bf_getbuffer
and bf_releasebuffer
fields), since these are part of the C API inheritance. But the pybind11 specific tinfo->get_buffer
does not get inherited from the parent class, resulting in the "generic_type::getbuffer(): Internal error"
exception.
Metadata
Metadata
Assignees
Labels
No labels