Accessing view of a NumPy array using the C API
The view of the array is just another information-wrapper for the same data array. Numpy
doesn't copy any data here. Only the information for the interpretation of the data are adjusted and the pointer to the data moved if useful.
In your code you're assuming, that the data of a vector a[:, 3]
is represented as a vector in memory which wouldn't differ for NPY_ARRAY_CARRAY
and NPY_ARRAY_FARRAY
. But this representation you only get after creating a (fortran ordered) copy of the array itself.
To make it work I modified your convertPyArrayToArma()
function a little to create a copy even if it's a vector:
template<typename outT>static arma::Mat<outT> convertPyArrayToArma(PyArrayObject* pyarr, int nrows, int ncols){ if (!checkPyArrayDimensions(pyarr, nrows, ncols)) throw WrongDimensions(); int arrTypeCode; if (std::is_same<outT, uint16_t>::value) { arrTypeCode = NPY_UINT16; } else if (std::is_same<outT, double>::value) { arrTypeCode = NPY_DOUBLE; } else { throw NotImplemented(); } PyArray_Descr* reqDescr = PyArray_DescrFromType(arrTypeCode); if (reqDescr == NULL) throw std::bad_alloc(); PyArrayObject* cleanArr = (PyArrayObject*)PyArray_FromArray(pyarr, reqDescr, NPY_ARRAY_FARRAY); if (cleanArr == NULL) throw std::bad_alloc(); reqDescr = NULL; // The new reference from DescrFromType was stolen by FromArray const auto dims = getPyArrayDimensions(pyarr); outT* dataPtr = static_cast<outT*>(PyArray_DATA(cleanArr)); // this copies the data from cleanArr arma::Mat<outT> result; if (dims.size() == 1) { result = arma::Col<outT>(dataPtr, dims[0], true); } else { result = arma::Mat<outT>(dataPtr, dims[0], dims[1], true); } Py_DECREF(cleanArr); return result;}