2012-02-27 14 views
6

He implementado una clase con std::map en C++ y he creado una interfaz usando SWIG para llamar desde Java. Sin embargo, no hay ningún objeto iterador que me permita iterar a través de las entradas en el SWIG envuelto std::map. ¿Alguien sabe cómo crear un iterador?No hay iterador para Java cuando se usa SWIG con el código estándar de C++

+0

Deberá precisar a qué se refiere con las entradas que no son "todas". ¿Algo específico, como el último artículo que falta? ¿Compartes algún código para mostrarnos cómo hiciste la interoperabilidad? –

+0

Lo siento, para ser precisos, no puedo realizar ninguna iteración. – delita

+1

Una búsqueda rápida en Google encontró esto: http://chadretz.wordpress.com/2009/11/27/stl-collections-with-java-and-swig/ Quizás sea útil – Tim

Respuesta

10

Para poder iterar sobre un objeto en Java, debe implementar Iterable. Esto a su vez requiere una función miembro llamada iterator() que devuelve una implementación adecuada de Iterator.

De su pregunta no está del todo claro si los tipos que está utilizando en el mapa y si desea poder iterar sobre los pares (como lo haría en C++), las claves o los valores. Las soluciones a las tres variantes son sustancialmente similares, mi ejemplo a continuación escogió los valores.

Lo primero es lo primero, el preámbulo para el archivo de interfaz SWIG que utiliza para probar esto:

%module test 

%include "std_string.i" 
%include "std_map.i" 

Con el fin de aplicar la hoja de iterable he declarado, definido y envolví otra clase en el archivo de interfaz SWIG . Esta clase, MapIterator implementa la interfaz Iterator para nosotros. Es una mezcla de C++ envuelto y Java, donde uno fue más fácil que el otro para escribir. En primer lugar algunos Java, un typemap que da la interfaz que implementa y luego dos de los tres métodos requeridos para la interfaz Iterable, dada como un typemap:

%typemap(javainterfaces) MapIterator "java.util.Iterator<String>" 
%typemap(javacode) MapIterator %{ 
    public void remove() throws UnsupportedOperationException { 
    throw new UnsupportedOperationException(); 
    } 

    public String next() throws java.util.NoSuchElementException { 
    if (!hasNext()) { 
     throw new java.util.NoSuchElementException(); 
    } 

    return nextImpl(); 
    } 
%} 

Entonces suministramos el C++ parte de MapIterator, que tiene un privado implementación de todas excepto la excepción que arroja parte de next() y el estado necesario para el iterador (expresado en términos de std::map propio const_iterator).

%javamethodmodifiers MapIterator::nextImpl "private"; 
%inline %{ 
    struct MapIterator { 
    typedef std::map<int,std::string> map_t; 
    MapIterator(const map_t& m) : it(m.begin()), map(m) {} 
    bool hasNext() const { 
     return it != map.end(); 
    } 

    const std::string& nextImpl() { 
     const std::pair<int,std::string>& ret = *it++; 
     return ret.second; 
    } 
    private: 
    map_t::const_iterator it; 
    const map_t& map;  
    }; 
%} 

Por último tenemos que decir que el TRAGO std::map estamos envolviendo implementa la interfaz Iterable y proporcionar una función miembro adicional para los fines de envolver std::map que devuelve una nueva instancia de la clase MapIterator que acabamos de escribir:

%typemap(javainterfaces) std::map<int,std::string> "Iterable<String>" 

%newobject std::map<int,std::string>::iterator() const; 
%extend std::map<int,std::string> { 
    MapIterator *iterator() const { 
    return new MapIterator(*$self); 
    } 
} 

%template(MyMap) std::map<int,std::string>; 

Esto podría ser más genérica, con macros, por ejemplo, para ocultar los tipos de la hoja de tal manera que si tiene varios mapas es sólo una cuestión de "llamada" la macro para los mapas apropiados al igual que se hace con %template .

También hay una ligera complicación con mapas de tipos primitivos - que tendrá que hacer arreglos para el lado de Java para utilizar Double/Integer en lugar de double/int (autoboxing Creo que es el término), a menos que se decidió para envolver pares ya en ese caso podrías hacer un par con los miembros primitivos.

Cuestiones relacionadas