I have a C++ library which currently has some methods inside which return a std::vector
defined like
我有一个c++库,它现在有一些方法可以返回std::向量定义的。
public:
const std::vector<uint32_t>& getValues() const;
I'm currently working on wrapping the whole library for Python using SWIG and this is working well so far.
我目前正在使用SWIG为Python包装整个库,到目前为止效果很好。
SWIG wraps this getValues()
function fine such that it returns a Python tuple. The issue is in my Python-side code I want to convert this to a NumPy array. Of course I can do this by:
SWIG将getValues()函数包装得很好,这样它就会返回一个Python元组。问题是在我的python代码中,我想把它转换成一个NumPy数组。当然我可以这样做:
my_array = np.array(my_object.getValues(), dtype='uint32')
but this causes all the entries in the original vector to be first copied into a Python tuple by SWIG and then again into a numpy array by me. Since this vector could be very large, I'd rather avoid making these two copies and would like for a way to have SWIG create a numpy.array wrapper around the original vector data in memory.
但是这会导致原始向量中的所有条目首先被SWIG复制到一个Python元组中,然后再被我复制到一个numpy数组中。由于这个向量可能很大,所以我宁愿避免做这两个拷贝,并希望有一种方法可以让SWIG创建一个numpy。在内存中围绕原始向量数据的数组包装器。
I've read the documentation for numpy.i but that explicitly mentions that output arrays are not supported since they seem to be working under the assumption of C-style arrays rather than C++ vectors.
我读过numpy的文档。但是,这明确地提到了不支持输出数组,因为它们似乎是在假设C样式数组而不是c++向量的情况下工作的。
numpy.array's underlying data structure is just a C-style array as is a C++ std::vector so I would hope that it is feasible to have then access the same data in memory.
numpy。数组的底层数据结构只是一个C风格的数组,它是一个c++ std::vector,所以我希望在内存中访问相同的数据是可行的。
Is there any way to make SWIG return a numpy.array which doesn't copy the original data?
有什么办法可以让SWIG返回麻木。不复制原始数据的数组?
2 个解决方案
#1
8
Apparently it is trivial to "cast" a C++ vector to (C) array, see answer on this question: How to convert vector to array in C++
显然,将一个c++向量“转换”到(C)数组是很简单的,请参阅这个问题的答案:如何在c++中将向量转换为数组
Next you can create a numpy array which will use that C array without copying, see discussion here, or google for PyArray_SimpleNewFromData
.
接下来,您可以创建一个numpy数组,该数组将使用该C数组而无需复制,请参阅这里的讨论,或者PyArray_SimpleNewFromData的谷歌。
I wouldn't expect SWIG to do all these for you automatically, instead you should probably write a wrapper for your function getValues
yourself, something like getValuesAsNumPyArray
.
我不希望SWIG自动为你做这些,相反,你应该为自己的函数编写一个包装器,比如getValuesAsNumPyArray。
#2
1
It seems like PyArray_SimpleNewFromData
would require you to do your own memory management; if memory management is already handled on the C++ side, that is, Python is not responsible for the memory, you can just use np.asarray
to get a numpy array that shares memory with the C++ vector, like so:
看起来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])
The "Wrapping C and C++ Arrays" section in chapter 10 of Kurt Smith's Cython book provides good examples on this. Also see Coercion to Numpy from official user guide.
库尔特·史密斯的Cython书第10章中的“包装C和c++数组”一节提供了很好的例子。还可以从官方用户指南中看到对Numpy的强制。
#1
8
Apparently it is trivial to "cast" a C++ vector to (C) array, see answer on this question: How to convert vector to array in C++
显然,将一个c++向量“转换”到(C)数组是很简单的,请参阅这个问题的答案:如何在c++中将向量转换为数组
Next you can create a numpy array which will use that C array without copying, see discussion here, or google for PyArray_SimpleNewFromData
.
接下来,您可以创建一个numpy数组,该数组将使用该C数组而无需复制,请参阅这里的讨论,或者PyArray_SimpleNewFromData的谷歌。
I wouldn't expect SWIG to do all these for you automatically, instead you should probably write a wrapper for your function getValues
yourself, something like getValuesAsNumPyArray
.
我不希望SWIG自动为你做这些,相反,你应该为自己的函数编写一个包装器,比如getValuesAsNumPyArray。
#2
1
It seems like PyArray_SimpleNewFromData
would require you to do your own memory management; if memory management is already handled on the C++ side, that is, Python is not responsible for the memory, you can just use np.asarray
to get a numpy array that shares memory with the C++ vector, like so:
看起来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])
The "Wrapping C and C++ Arrays" section in chapter 10 of Kurt Smith's Cython book provides good examples on this. Also see Coercion to Numpy from official user guide.
库尔特·史密斯的Cython书第10章中的“包装C和c++数组”一节提供了很好的例子。还可以从官方用户指南中看到对Numpy的强制。