I see how to consume and alter a numpy.array (of doubles) binded to a py::array X by using X.request().shape to have the dimensions and then using static_cast<double*>(X.request().ptr) to get the coefficients. Now, I would like to implement a matrix (2D numpy.array) product (using various libraries, mkl among all, to do a benchmark), so that in my c++ function I would have to construct a py::array, fill properly its ptr and other members and return it, but I don't have a clue about how to do it. Seems that there is a strides member depending on the double size and the dimension etc. Where could I find sufficiently generic example, of a complete documentation about py::array ?
To create a matrix as a py::array you have to give to the py::array constructor a pre-filled py::buffer_info,
so doing something like this should work (this is what I use to create images)
template<class T>
py::array<T> create_matrix(size_t width, size_t height, T data_ptr = nullptr)
{
return py::array_t<T>(
py::buffer_info(
data_ptr,
sizeof(T), //itemsize
py::format_descriptor<T>::format(),
2, // ndim
std::vector<size_t> { width, height }, // shape
std::vector<size_t> {height * sizeof(T), sizeof(T)} // strides
)
)
}
if data_ptr is nullptr then the py::array wil allocate memory for you, if it is not it will copy de data from the data_ptr (if I remember correctly)
You don't have to go through buffer_info for this: array and array_t have a bunch of different constructors taking shapes and strides.
The simplest version, to create a new array that allocates contiguous memory storage, is to use:
py::array_t<double> arr({ 3, 5 }); // creates a 3x5 matrix with C-style contiguous storage
However something you'll quickly run into is that a lot of libraries actually expect and use column-major storage (numpy calls this "Fortran style"), while numpy defaults to row-major (AKA "C-style"). (https://en.wikipedia.org/wiki/Row-_and_column-major_order). If you need column-major, you can use:
py::array_t<double, py::array::f_style> arr({ 3, 5 });
For ordinary contiguous arrays you don't need to worry about the strides: py::array will set those up for you properly for contiguous storage when you create the array. The only case you'd need to worry about specifying them is where you have non-contiguous storage.
There are various other examples of different ways to construct arrays in the test suite (tests/test_numpy_array.cpp).
Answered extensively (thanks, @jagerman!), and no further reply. Closing.
Most helpful comment
To create a matrix as a py::array you have to give to the py::array constructor a pre-filled py::buffer_info,
so doing something like this should work (this is what I use to create images)
if data_ptr is nullptr then the py::array wil allocate memory for you, if it is not it will copy de data from the
data_ptr(if I remember correctly)