2011-03-10 14 views
9

Estoy enfrentando un problema similar al Wrap std::vector of std::vectors, C++ SWIG Python, pero no es solo un simple análisis de C++. Tengo el siguiente en mi código C++SWIG vector envuelto de vectores (C++ a python): ¿cómo reconocer el vector interno como un objeto proxy?

namespace ns { 
    typedef unsigned long long uint64_t; 
    typedef std::vector<uint64_t> Vector; 
    typedef std::vector<Vector> VectorOfVectors; 

    class MyClass { 
     /// ... 

     /// Returns a reference to the internal vector allocated in C++ land 
     const VectorOfVectors &GetVectors() const; 
    }; 
} 

Y en la envoltura TRAGO

%module myswig  
// ... 
%template(Uint64V) std::vector<ns::uint64_t>; 
%template(VUint64V) std::vector<std::vector<ns::uint64_t> >; 

Así que la envoltura funciona bien, incluyendo la clase, y puedo recuperar vectorial de los vectores de la clase OK:

import myswig 
m = myswig.MyClass() 
v = m.GetVectors() 
print v 

Lo que me da:

<myswig.VUint64V; proxy of <Swig Object of type 'std::vector< std::vector< ns::uint64_t,std::allocator<ns::uint64_t> > > *' at 0x994a050> > 

Pero si tengo acceso a un elemento en el vector, no obtengo un proxy que sea myswig.Uint64V, y este es mi problema.

x = v[0] 
print x 

Lo que me espero conseguir es:

<myswig.Uint64V; proxy of <Swig Object of type 'std::vector< ns::uint64_t, std::allocator<ns::uint64_t> > *' at 0x994a080> > 

En cambio, yo estoy haciendo:

(<Swig Object of type 'ns::uint64_t *' at 0x994a080>, <Swig Object of type 'ns::uint64_t *' at 0x994a098>) 

Es decir, el índice en el vector de vectores me está dando una tupla de 2 entradas, y no un proxy para la clase vectorial que necesito (de modo que acceder al vector interno es tan fácil como acceder a otros vectores).

Yo también estoy haciendo la advertencia:

swig/python detected a memory leak of type 'ns::uint64_t *', no destructor found. 

porque por supuesto no es un destructor definido para este tipo.

¿Alguna idea?

Respuesta

10

Trabajé en esto con un colega mío, y hemos logrado encontrar algunas soluciones.

En primer lugar, en el archivo .i TRAGO, es importante definir esta variable preprocesador:

%{ 
# define SWIG_PYTHON_EXTRA_NATIVE_CONTAINERS 
%} 

Y luego, para asegurar que las referencias regresaron de métodos tales como delantero(), atrás() , el operador [], etc están ocupadas con el tipo de proxy correcta para el vector interno, la ayuda typemaps siguientes:

// In pop() 
%typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type { 
$result = SWIG_NewPointerObj(SWIG_as_voidptr(&$1), $descriptor(std::vector<ns::uint64_t>), 0 | 0); 
} 

// In front(), back(), __getitem__() 
%typemap(out) std::vector<std::vector<ns::uint64_t> >::value_type & { 
    $result = SWIG_NewPointerObj(SWIG_as_voidptr($1), $descriptor(std::vector<ns::uint64_t>), 0 | 0); 
} 

también descubrimos que si desea que los ns :: uint64_t a ser entendido como una serpiente pitón de largo variable (equivalente a un C largo largo sin signo) y luego un mapa de tipos adicional s fueron necesarios para garantizar que los métodos vectoriales que utilizan valores y referencias simplemente utilicen valores enteros de 64 bits.

// In __getitem__() 
%typemap(out) ns::uint64_t { 
    $result = PyLong_FromUnsignedLongLong($1); 
} 
// Not used (but probably useful to have, just in case) 
%typemap(in) ns::uint64_t { 
    $1 = PyLong_AsUnsignedLongLong($input); 
} 
// In pop() 
%typemap(out) std::vector<ns::uint64_t>::value_type { 
    $result = PyLong_FromUnsignedLongLong($1); 
} 
// In __getitem__(), front(), back() 
%typemap(out) std::vector<ns::uint64_t>::value_type & { 
    $result = PyLong_FromUnsignedLongLong(*$1); 
} 
// In __setitem__(), append(), new Uint64Vector, push_back(), assign(), resize(), insert() 
// This allows a python long literal number to be used as a parameter to the above methods. 
// Note the use of a local variable declared at the SWIG wrapper function scope, 
// by placing the variable declaration in parentheses() prior to the open brace { 
%typemap(in) std::vector<ns::uint64_t>::value_type & (std::vector<ns::uint64_t>::value_type temp) { 
    temp = PyLong_AsUnsignedLongLong($input); 
    $1 = &temp; 
} 

Espero que esta solución ayude a las personas en el futuro.

+0

Tengo un problema con la referencia de const y el puntero y const puntero vinculante, ¿podría proporcionar más información? – squid

+0

La línea de definición es tan importante ... pero es tan ... poco llamativa al mismo tiempo. Me pregunto cómo lo encontrará. – squid

Cuestiones relacionadas