如何使用 <numpy/arrayobject.h> 在 c++ 中将数据从 np.array 获取到 std::vector?
Posted
技术标签:
【中文标题】如何使用 <numpy/arrayobject.h> 在 c++ 中将数据从 np.array 获取到 std::vector?【英文标题】:How to get data from np.array to std::vector in c++ using <numpy/arrayobject.h>? 【发布时间】:2017-12-16 18:01:40 【问题描述】:这是我在这个网站上的第一个问题。
首先,我需要使用<numpy/arrayobject.h>
为C++ 中的python 创建一个具有一个函数的模块,该模块必须与numpy 一起使用。此函数接受一个 numpy 数组并返回两个 numpy 数组。所有数组都是一维的。
第一个问题是如何从一个numpy数组中获取数据?我想从 std::vector 中的数组中收集信息,这样我就可以轻松地使用它 C++。
第二个:这个函数应该返回一个数组元组,然后我的模块的用户可以在 python 中这样写:
arr1, arr2 = foo(arr)
?
又该如何返回呢?
非常感谢。
【问题讨论】:
您可以查看***.com/help/how-to-ask 以改进提问方式。 既然你是 C++,我会调查PyBind11。 【参考方案1】:NumPy 包含lots of functions and macros,这使得在 C 或 C++ 扩展中访问 ndarray
对象的数据变得非常容易。给定一个名为v
的一维ndarray
,可以使用PyArray_GETPTR1(v, i)
访问元素i
。因此,如果您想将数组中的每个元素复制到同一类型的 std::vector
中,您可以遍历每个元素并复制它,就像这样(我假设一个 double
s 的数组):
npy_intp vsize = PyArray_SIZE(v);
std::vector<double> out(vsize);
for (int i = 0; i < vsize; i++)
out[i] = *reinterpret_cast<double*>(PyArray_GETPTR1(v, i));
也可以执行类似memcpy
的批量操作,但请记住,NumPy ndarray
s 可能与数据类型不对齐、具有非本机字节顺序或其他导致此类操作的微妙属性副本少于理想。但假设你知道这些,你可以这样做:
npy_intp vsize = PyArray_SIZE(v);
std::vector<double> out(vsize);
std::memcpy(out.data(), PyArray_DATA(v), sizeof(double) * vsize);
无论使用哪种方法,out
现在都包含ndarray
数据的副本,您可以随意操作它。请记住,除非您确实需要 std::vector
形式的数据,否则 NumPy C API 可能非常适合在您的扩展程序中用作访问和操作数据的一种方式。也就是说,除非您需要将数据传递给必须采用std::vector
的其他函数,或者您想使用依赖于std::vector
的C++ 库代码,否则我会考虑做所有您的直接在原生数组类型上处理。
关于您的最后一个问题,通常使用PyArg_BuildValue
构造一个从您的扩展函数返回的元组。您的元组将只包含两个 ndarray
对象。
【讨论】:
非常感谢!所以,我还可以通过调用函数PyArray_GetArrayParamsFromObject
来获取有关numpy数组形状的信息?然后我想返回对象的形状是一样的
@InFamousX 这可以正常工作,但更常见的是使用宏 PyArray_NDIM()
和 PyArray_DIMS()
。前一个函数更常用于将 Python 原生对象(如列表列表)转换为 ndarray
。
抱歉,这个循环for(int ...)
不能正常工作,因为我从中得到的只有零。
@InFamousX 该循环应该可以正常访问数据,您确定数组本身不是全零吗?
谢谢,我找到了另一种获取数据的方法。我的错误是我不知道 python 中的 float 与 c++ 中的 double 相同。这就是为什么我只得到零。以上是关于如何使用 <numpy/arrayobject.h> 在 c++ 中将数据从 np.array 获取到 std::vector?的主要内容,如果未能解决你的问题,请参考以下文章