Sayı dizilerini SWIG ile <int> & (başvuru) vektörüne dönüştürme


10

Amacım:

Python'da 3 numpy dizisi oluşturun (bunlardan 2 tanesi belirli değerlerle başlatılır), sonra üçünü de swig yoluyla vektör referansları olarak bir c ++ fonksiyonuna gönderin (bu, verilerin üzerine kopyalanmayı ve verimliliği kaybetmeyi önlemek içindir). C ++ işlevine girdikten sonra dizilerden 2'sini ekleyin ve toplamlarını 3. diziye koyun.

vec_ref.h

#include <vector>
#include <iostream>

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

vec_ref.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_ref.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

tester.py

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)

Çıktı:

---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 > > &'

Ben vec_ref.i bulunan tüm yorum% uygulandı ve% şablon yönergeleri denedim, ama işe yaramadı.

Olmamam da dahil olmak üzere bazı tipemapler var mı?


3
Bu mümkün değil. C ++ 'da, yalnızca gerçekte var olan nesnelere referans oluşturabilirsiniz. Ancak, numpy dizileri a içermez std::vector.
pschill

Yanıtlar:


3

@Pschill ile aynı fikirdeyim: Veri kopyalamadan std :: vector almak mümkün değil.

Alternatif olarak std::spansınıf şablonu (C ++ 20'de tanıtıldı) veya spanbir kitaplıkta tanımlanan benzer bir sınıf şablonu kullanmaktır.

Bir oluşturma std::span<int>bir sağlayacak görünümü , bir mevcut veri numpydizisinin ve temin birçok kullanışlı üye işlevlerini (örneğin operator[]yineleyicileri, front(), back()C ++, vs.).

Span oluşturmak asla numpy dizisinden veri kopyalamaz.


En iyi alternatif olarak gördüğümü sağladığınız için teşekkürler (kendi sınıfımı oluşturmanın yanı sıra).
Otherness

Gerçekten C ++ fonksiyonumda kopyalamadan bir std :: vector kullanmak (ve değiştirmek) isteseydim, ne gibi alternatiflerim olurdu? Std :: raw için işaretçi vektör? std :: vector?
Gabriel Devillers

@GabrielDevillers, eğer sorunuzu anlarsam, bir vektör varsa ve fonksiyonunuzda değiştirmek istiyorsanız, vector'a bir referans kullanmanızı tavsiye ederim : std::vector<T>& v
NicholasM

@NicholasM SWIG kullanarak sarmak istediğim bir API demek istedim. Soruyorum çünkü SWIG'nin vektörlere const olmayan referansı sartamayacağını anlıyorum.
Gabriel Devillers

Ay pardon. Özel durumunuza odaklanan yeni bir soru oluşturmanızı öneririm.
NicholasM

0

Daha zarif bir şekilde elde etmek istediğiniz şeyi elde eden Facebook başarısız kütüphanesine başvurabilirsiniz.

Python'a özgü: numpy dizisi <-> C ++ işaretçi arabirimi (vektör)

Kodu Github sayfasında görebilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.