2013-11-21 7 views
5

Sto avendo un sacco di problemi nel tentativo di avvolgere un metodo C++ che restituisce un riferimento costante a un vettore di coppie in una lista Python di tuple usando %typemap(out).Vettore di ritorno <coppia <int,int>> & dal metodo C++ alla lista python di tuple usando la typemap di swig

Al momento ho qualcosa di simile:

MyClass.h:

#inlcude <vector> 
using std::vector; 
class MyClass { 
private: 
    const vector<pair<int,int>> & _myvector; 
public: 
    MyClass(const vector<pair<int,int>> & myvector); 
    const vector<pair<int,int>> & GetMyVector() const; 
} 

MyClass.cpp:

#include "myclass.h" 

MyClass::MyClass(const vector<pair<int,int>> & myvector): _myvector(myvector){}; 

const vector<pair<int,int>> & MyClass::GetMyVector() const { 
    return _myvector; 
}; 

MiaClasse.i: (CONTROLLO ommited)

%module MyClass 
%include "std_vector.i" 

namespace std { 
    %template(vector_pair_int) vector<pair<int,int>>; 
} 

%typemap(in) (const vector_pair_int &){ 

    $1 = new vector<pair<int,int>>; 
    int size = PyList_Size($input); 
    for (int i=0; i<size; i++){ 
     PyObject *o = PyList_GetItem($input,i); 
     PyObject *o1 = PyList_GetItem(o,0); 
     PyObject *o2 = PyList_GetItem(o,1); 
     $1->push_back(make_pair(PyInt_AsLong(o1),PyInt_AsLong(o2))) 
} 

} 

%typemap(out) (const vector_pair_int &) { 
    $result = PyList_New($1.size()); 
    vector<pair<int,int>>:: const_iterator it; 
    int count=0; 
    for (it= $1.begin(); it!= $1.end(); ++it){ 
     PyObject * tup = PyTuple_Pack(2, it->first,it->second); 
     PyList_SET_ITEM($result,count,tup); 
     count++; 
    } 
} 

Ok così il primo t Ciò che non capisco è che il codice precedente per la typemap (out) non viene compilato perché mi dice che $ 1 è un puntatore al contenitore e non un riferimento. Quando cambio l'uso di $ 1 come puntatore, esso compila ma non funziona.

In secondo luogo, nel caso in cui compila, la typemap (in) funziona (il contenitore C++ è riempito correttamente), ma quando provo a recuperare il contenitore da python ottengo garbage. Quando passo al costruttore qualcosa come MyClass ([(1,2)]), e poi uso GetMyVector() restituisce una lista python ma di dimensione 3 e con garbage sulle tuple ... cosa sto facendo male ???

risposta

7

In questo caso non è necessaria una typemap personalizzata. SWIG è dotato di supporto per i vettoriali e coppia di modelli, ma si deve dichiarare il modello di coppia così come il modello di vettore:

%module x 

%include <std_pair.i> 
%include <std_vector.i> 
%include <std_string.i> 
%template() std::pair<int,int>; 
%template(PairVector) std::vector<std::pair<int,int> >; 

%{ 
#include "MyClass.h" 
%} 

%include "MyClass.h" 

Esempio:

>>> import x 
>>> a=x.PairVector(((1,2),(3,4),(5,6))) 
>>> b=x.MyClass(a) 
>>> b.GetMyVector() 
((1, 2), (3, 4), (5, 6)) 

ma nota perché la classe è scritto per mantenere un riferimento al vettore passato e non una copia, devi tenere un riferimento ad esso per tutta la vita di MyClass. Ad esempio:

>>> del a 
>>> b.GetMyVector() 
*Undefined Behavior (crash, empty vector, etc.)* 
Problemi correlati