如何使用 <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 【问题描述】:

这是我在这个网站上的第一个问题。

首先,我需要使用&lt;numpy/arrayobject.h&gt; 为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 中,您可以遍历每个元素并复制它,就像这样(我假设一个 doubles 的数组):

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 ndarrays 可能与数据类型不对齐、具有非本机字节顺序或其他导致此类操作的微妙属性副本少于理想。但假设你知道这些,你可以这样做:

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?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 XML 设置样式

如何使用 xslt 转换 xml?

如何使用 flexbox 将项目右对齐?

如何避免使用 <canvas> 旋转的图像截断?

如何使用 jQuery 修改属性 ROWSPAN?

如何使用 ArrayAdapter<myClass>