Cách chuyển đổi mảng numpy thành vectơ <int> & (tham chiếu) với SWIG


10

Mục tiêu của tôi:

Tạo 3 mảng numpy trong python (2 trong số chúng sẽ được khởi tạo với các giá trị cụ thể), sau đó gửi cả ba mảng qua swig vào hàm c ++ dưới dạng tham chiếu vector (điều này để tránh sao chép dữ liệu và mất hiệu quả). Khi đã ở trong hàm c ++, hãy thêm 2 mảng và đặt tổng của chúng vào mảng thứ 3.

vec numf.h

#include <vector>
#include <iostream>

void add_vec_ref(std::vector<int>& dst, std::vector<int>& src1, std::vector<int>& src2);

vec numf.cpp

#include "vec_ref.h"
#include <cstring> // need for size_t
#include <cassert>

void add_vec_ref(std::vector<int>& dst, std::vector<int>& src1, std::vector<int>& src2) {
    std::cout << "inside add_vec_ref" << std::endl;
    assert(src1.size() == src2.size());
    dst.resize(src1.size());

    for (size_t i = 0; i < src1.size(); i++) {
        dst[i] = src1[i] + src2[i];
    }
}

vec numf.i

%module vec_ref
%{
    #define SWIG_FILE_WITH_INIT
    #include "vec_ref.h"
%}

%include "numpy.i"
%init %{
import_array();
%}

%include "std_vector.i"
%template(vecInt) std::vector<int>;
// %template(vecIntRef) std::vector<int> &; 

// %apply (std::vector<int> * INPLACE_ARRAY1, int DIM1) {(std::vector<int> * dst, int a),(std::vector<int> * src1, int b),(std::vector<int> * src2, int c)};
// %apply (std::vector<int> * INPLACE_ARRAY1) {(std::vector<int> * dst),(std::vector<int> * src1),(std::vector<int> * src2)};
// %apply (std::vector<int> & INPLACE_ARRAY1) {(std::vector<int> & dst),(std::vector<int> & src1),(std::vector<int> & src2)};
// %apply (std::vector<int> & INPLACE_ARRAY1, int DIM1) {(std::vector<int> & dst, int a),(std::vector<int> & src1, int b),(std::vector<int> & src2, int c)};

%include "vec_ref.h"

Makefile

all:
    rm -f *.so *.o *_wrap.* *.pyc *.gch vec_ref.py
    swig -c++ -python vec_ref.i
    g++ -O0 -g3 -fpic -c vec_ref_wrap.cxx vec_ref.h vec_ref.cpp -I/home/lmckeereid/tools/anaconda3/pkgs/python-3.7.3-h0371630_0/include/python3.7m/
    g++ -O0 -g3 -shared vec_ref_wrap.o vec_ref.o -o _vec_ref.so

người kiểm tra

import vec_ref as vec
import numpy as np

a = np.array([1,2,3], dtype=np.intc)
b = np.array([4,5,6], dtype=np.intc)
c = np.zeros(len(a), dtype=np.intc)

print('---Before---\na:', a)
print('b:', b)
print('c:', c)

vec.add_vec_ref(c,a,b)

print('---After---\na:', a)
print('b:', b)
print('c:', c)

Đầu ra:

---Before---
a: [1 2 3]
b: [4 5 6]
c: [0 0 0]
Traceback (most recent call last):
  File "tester.py", line 12, in <module>
    vec.add_vec_ref(c,a,b)
TypeError: in method 'add_vec_ref', argument 1 of type 'std::vector< int,std::allocator< int > > &'

Tôi đã thử tất cả các chỉ thị% áp dụng và% mẫu được tìm thấy trong vec numf.i, nhưng chúng không hoạt động.

Có một số kiểu chữ mà tôi nên đưa vào mà tôi không?


3
Đó là không thể. Trong C ++, bạn chỉ có thể tạo tham chiếu đến các đối tượng thực sự tồn tại. Tuy nhiên, mảng numpy không chứa a std::vector.
pschill

Câu trả lời:


3

Tôi đồng ý với @pschill: không thể lấy std :: vector mà không sao chép dữ liệu.

Một cách khác là sử dụng std::spanmẫu lớp (được giới thiệu trong C ++ 20) hoặc spanmẫu lớp tương tự được xác định trong thư viện.

Tạo một std::span<int>sẽ cung cấp một cái nhìn của dữ liệu hiện có trong một numpymảng, và cung cấp nhiều chức năng thành viên thuận tiện (ví dụ như operator[], vòng lặp, front(), back(), vv) trong C ++.

Tạo một khoảng sẽ không bao giờ sao chép dữ liệu từ mảng numpy.


Cảm ơn vì đã cung cấp những gì tôi thấy là sự thay thế tốt nhất (ngoài việc xây dựng lớp học của riêng tôi).
Khác 18/11/19

Nếu tôi thực sự muốn sử dụng (và sửa đổi) một std :: vector trong hàm C ++ của mình mà không cần sao chép, tôi sẽ có những lựa chọn thay thế nào? Con trỏ thô để std :: vector? shared_ptr để std :: vector?
Gabriel Devillers

@GabrielDevillers, nếu tôi hiểu câu hỏi của bạn, nếu một vectơ tồn tại và bạn muốn sửa đổi nó trong chức năng của mình, tôi khuyên bạn nên sử dụng một tham chiếu đến vectơ: std::vector<T>& v
NicholasM

@NicholasM Ý tôi là trong một API mà tôi muốn bọc bằng SWIG. Tôi đang hỏi bởi vì tôi hiểu rằng SWIG không thể bao bọc tham chiếu không liên quan đến vectơ.
Gabriel Devillers

Ồ xin lỗi. Tôi đề nghị bạn tạo một câu hỏi mới tập trung vào trường hợp cụ thể của bạn.
NicholasM

0

Bạn có thể tham khảo thư viện faiss của Facebook, nơi đạt được những gì bạn muốn đạt được, theo cách thanh lịch hơn Bởi:

Cụ thể của Python: mảng numpy <-> Giao diện con trỏ C ++ (vector)

Bạn có thể xem mã trên trang Github của nó .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.