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

2024-04-27 03:04:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个C++库,里面有一些方法,里面返回一个^ {< CD1>},定义为

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包装器。

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

数组的底层数据结构只是一个C样式数组,它是C++的STD::vector,所以我希望在内存中访问相同的数据是可行的。

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


Tags: 数据方法内存numpymy样式数组array
2条回答
显然,将C++向量“(c)”数组“投”是微不足道的,请参阅这个问题的答案:How to convert vector to array in C++

接下来,您可以创建一个numpy数组,它将在不复制的情况下使用该C数组,请参见discussion here,或者google for PyArray_SimpleNewFromData

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

<^ >看起来{{CD1}}需要你自己做内存管理;如果内存管理已经在C++端上处理,也就是说Python对内存不负责,你可以使用^ {CD2>}来获得一个与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])
< Kurt Smith的Cython书第10章中的“包装C和C++数组”部分提供了很好的例子。另请参见Coercion to Numpy from official user guide

相关问题 更多 >