将std :: vector转换为NumPy数组而不复制数据

时间:2013-04-17 16:17:38

标签: c++ python numpy swig

我有一个C ++库,目前有一些方法可以返回std::vector定义的

public:
  const std::vector<uint32_t>& getValues() const;

我目前正在使用SWIG为Python包装整个库,到目前为止这种方法运行良好。

SWIG将此getValues()函数包装好,以便返回Python元组。问题出在我的Python端代码中,我希望将其转换为NumPy数组。我当然可以这样做:

my_array = np.array(my_object.getValues(), dtype='uint32')

但是这会导致原始向量中的所有条目首先被SWIG复制到Python元组中,然后由我再次复制到numpy数组中。由于这个向量可能非常大,我宁愿避免制作这两个副本,并希望有一种方法可以让SWIG在内存中创建一个numpy.array包装原始向量数据。

我已经阅读了numpy.i的文档,但明确提到输出数组不受支持,因为它们似乎是在C样式数组而不是C ++向量的假设下工作。

numpy.array的底层数据结构只是一个C风格的数组,就像C ++ std :: vector一样,所以我希望在内存中访问相同的数据是可行的。

有没有办法让SWIG返回一个不会复制原始数据的numpy.array?

2 个答案:

答案 0 :(得分:8)

显然,将C ++向量“转换”为(C)数组是微不足道的,请参阅这个问题的答案:How to convert vector to array in C++

接下来,您可以创建一个numpy数组,该数组将使用该C数组而不进行复制,请参阅discussion here或google for PyArray_SimpleNewFromData

我不希望SWIG自动为您完成所有这些操作,相反,您应该自己为函数getValues编写一个包装器,类似getValuesAsNumPyArray

答案 1 :(得分:2)

似乎PyArray_SimpleNewFromData要求你做自己的记忆管理;如果已经在C ++端处理了内存管理,也就是说,Python不负责内存,你只需使用np.asarray来获得一个与C ++向量共享内存的numpy数组,如下所示:

from libcpp.vector cimport vector
import numpy as np
cdef vector[double] vec
vec.push_back(1)
vec.push_back(2)
cdef double *vec_ptr = &vec[0]    # get hold of data array underlying vec; also vec.data() if you have C++11
cdef double[::1] vec_view = <double[:vec.size()]>vec_ptr    # cast to typed memory view
vec_npr = np.asarray(vec_view)    # get numpy array from memory view
print(vec_npr)    # array([1.0, 2.0])

&#34;包装C和C ++数组&#34; Kurt Smith的Cython书第10章中的一节提供了很好的例子。另请参阅Coercion to Numpy from official user guide