2013-04-17 36 views
9

Tôi có một thư viện C++ mà hiện nay có một số phương pháp trong đó trả về một std::vector định nghĩa như thếChuyển đổi một std :: vector để một mảng NumPy mà không cần sao chép dữ liệu

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

Tôi hiện đang làm việc trên gói toàn bộ thư viện cho Python sử dụng SWIG và điều này đang hoạt động tốt cho đến nay.

SWIG kết thúc tốt đẹp chức năng này getValues() sao cho nó trả về bộ túp Python. Vấn đề là trong mã phía Python của tôi, tôi muốn chuyển đổi này thành một mảng NumPy. Tất nhiên tôi có thể làm điều này bằng cách:

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

nhưng điều này làm cho tất cả các mục trong vector ban đầu được sao chép lần đầu vào một tuple Python bởi SWIG và sau đó lại trở thành mảng cứng nhắc của tôi. Vì vectơ này có thể rất lớn, tôi muốn tránh tạo hai bản sao này và muốn có một cách để SWIG tạo ra một bao bọc numpy.array xung quanh dữ liệu vectơ ban đầu trong bộ nhớ.

Tôi đã đọc tài liệu cho numpy.i nhưng rõ ràng đề cập rằng mảng đầu ra không được hỗ trợ vì chúng dường như hoạt động dưới giả định của mảng kiểu C chứ không phải vectơ C++.

Cấu trúc dữ liệu cơ bản của numpy.array chỉ là một mảng kiểu C như là một C++ std :: vectơ vì vậy tôi hy vọng có thể truy cập vào cùng một dữ liệu trong bộ nhớ.

Có cách nào để làm cho SWIG trả lại giá trị numpy.array không sao chép dữ liệu gốc không?

Trả lời

8

Rõ ràng nó là tầm thường để "đúc" một C++ vector để mảng (C), xem câu trả lời về câu hỏi này: How to convert vector to array in C++

Tiếp theo, bạn có thể tạo một mảng NumPy mà sẽ sử dụng mảng C mà không sao chép, xem discussion here hoặc google cho PyArray_SimpleNewFromData.

Tôi không mong đợi SWIG thực hiện tất cả những điều này cho bạn một cách tự động, thay vào đó bạn có lẽ nên viết một trình bao bọc cho hàm của bạn getValues chính mình, chẳng hạn như getValuesAsNumPyArray.

0

Có vẻ như PyArray_SimpleNewFromData sẽ yêu cầu bạn phải tự quản lý bộ nhớ của mình; nếu quản lý bộ nhớ đã được xử lý ở bên C++, có nghĩa là, Python là không chịu trách nhiệm về bộ nhớ, bạn chỉ có thể sử dụng np.asarray để có được một mảng NumPy rằng chia sẻ bộ nhớ với C++ vector, như vậy:

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]) 

Phần "Gói C và C++" trong chương 10 của cuốn sách Cython của Kurt Smith cung cấp các ví dụ tốt về điều này. Xem thêm Coercion to Numpy from official user guide.

+0

Điều này khiến cho con trăn đổ vỡ cho tôi. – snowleopard

Các vấn đề liên quan