2012-05-15 19 views
6

intento generar el código de Java con el TRAGOstd :: vector para la generación de código java.util.Vector con trago

En MyList.h I declaró un objeto de lista personalizada llama _list

List<T*> _list; 

y esta lista clase hereda de vectores

class List : public vector<T> 

en una clase de negocios (en C++) regrese una batería de Li st de la costumbre objetos

List<MyObject> getMyList(){ 
    .... 
    return list; 
} 

por lo que quiero para generar el código de Java en el que puedo recuperar esta lista como C++ o java.util.List java.util.Vector.

en mi archivo swig.i no podía soportar cómo encarnar

%typemap(jstype) List "java.util.Vector" 
namespace std { 
    %template(CustomVector) vector<MyObject>; 
} 

cualquier tipo de ayuda sobre cómo configurar este archivo de plantilla swig.i o un código de ejemplo para generar un java.util.List/Se apreciará la función de retorno del vector.

Gracias.

+0

Por favor, echar un vistazo a http: // desbordamiento de pila.com/preguntas/1854335/cómo-a-crear-a-java-clase-similar a-ac-plantilla de clase y http://stackoverflow.com/questions/462297/how- to-use-classt-in-java – phantasmagoria

+2

En cuanto a la herencia 'std :: vector', eche un vistazo a [esta pregunta] (http://stackoverflow.com/questions/4353203/thou-shalt-not-inherit-from -stdvector). – juanchopanza

+0

OK digamos que no usaré/devolveré un std :: vector, entonces ¿cómo puedo transferir una lista de objetos desde la capa C++ a mi capa java? –

Respuesta

10

En realidad, no desea tocar java.util.Vector con sus interfaces envueltas porque terminará duplicando el almacenamiento o haciendo un gran número de operaciones de copia cada vez que lo transfiere o desaparece de una función. (Tenga en cuenta también que, en general, en C++ que se hereda de los contenedores es un diseño extraño).

En cambio, en Java, lo "correcto" es heredar de java.util.AbstractList. Esta respuesta es una versión más genérica de mi older answer to a similar question.

Funciona para todos los tipos std::vector, no solo un tipo fijo y maneja primitives which need to be accessed via Objects usando un mapa de tipo personalizado "autobox". Falta el soporte para el std::vector<bool> especializado, pero debería ser fácil de agregar si lo necesita.

%{ 
#include <vector> 
#include <stdexcept> 
%} 

%include <stdint.i> 
%include <std_except.i> 

namespace std { 

    template<class T> class vector { 
     public: 
     typedef size_t size_type; 
     typedef T value_type; 
     typedef const value_type& const_reference; 
     vector(); 
     vector(size_type n); 
     vector(const vector& o); 
     size_type capacity() const; 
     void reserve(size_type n); 
     %rename(isEmpty) empty; 
     bool empty() const; 
     void clear(); 
     void push_back(const value_type& x); 
     %extend { 
      const_reference get(int i) const throw (std::out_of_range) { 
       return $self->at(i); 
      } 
      value_type set(int i, const value_type& VECTOR_VALUE_IN) throw (std::out_of_range) { 
       const T old = $self->at(i); 
       $self->at(i) = VECTOR_VALUE_IN; 
       return old; 
      } 
      int32_t size() const { 
       return $self->size(); 
      } 
      void removeRange(int32_t from, int32_t to) { 
       $self->erase($self->begin()+from, $self->begin()+to); 
      } 
     } 
    }; 
} 

// Java typemaps for autoboxing in return types of generics 
%define AUTOBOX(CTYPE, JTYPE) 
%typemap(autobox) CTYPE, const CTYPE&, CTYPE& "JTYPE" 
%enddef 
AUTOBOX(double, Double) 
AUTOBOX(float, Float) 
AUTOBOX(boolean, Boolean) 
AUTOBOX(signed char, Byte) 
AUTOBOX(short, Short) 
AUTOBOX(int, Integer) 
AUTOBOX(long, Long) 
AUTOBOX(SWIGTYPE, $typemap(jstype,$1_basetype)) 

%typemap(javabase) std::vector "java.util.AbstractList<$typemap(autobox,$1_basetype::value_type)>" 
%typemap(javainterface) std::vector "java.util.RandomAccess" 
%typemap(jstype) std::vector get "$typemap(autobox,$1_basetype)" 
%typemap(jstype) std::vector set "$typemap(autobox,$1_basetype)" 
%typemap(jstype) std::vector &VECTOR_VALUE_IN "$typemap(autobox,$1_basetype)" 
%typemap(javacode) std::vector %{ 
    $javaclassname(java.util.Collection<$typemap(autobox,$1_basetype::value_type)> e) { 
    this.reserve(e.size()); 
    for($typemap(autobox,$1_basetype::value_type) value: e) { 
     this.push_back(value); 
    } 
    } 
%} 

mayoría de esto es bastante similar a la std_vector.i predeterminada que SWIG ofrece actualmente, los nuevos bits son el cambio de nombre, que se extiende y typemaps que se extienden AbstractList e implementan RandomAccess. También agrega un constructor que toma otros Collection s; esto es recomendado por la documentación de Java y lo suficientemente fácil de hacer. (Hay una sobrecarga para otros tipos de std::vector que es mucho más rápido).

He probado este vector envoltura dentro de otra interfaz SWIG:

%module test 

%include "vector.i" 

%template(DblVec) std::vector<double>; 
%template(ByteVec) std::vector<signed char>; 
%include <std_string.i> 
%template(StringVec) std::vector<std::string>; 

%inline %{ 
struct foo {}; 
%} 

%template(FooVec) std::vector<foo>; 

que pude para compilar y ejecutar con:

public class run { 
    public static void main(String argv[]) { 
    System.loadLibrary("test"); 
    DblVec dv = new DblVec(100); 
    for (int i = 0; i < 100; ++i) { 
     dv.set(i,(double)i); 
    } 
    FooVec fv = new FooVec(1); 
    fv.set(0, new foo()); 
    for (double d: dv) { 
     System.out.println(d); 
    } 
    } 
} 
+0

(Probado con SWIG 2.0.4) – Flexo

+0

Hola. ¿Todavía recomendaría usar este envoltorio en lugar de la implementación 'std_vector.i' de SWIG? Solo necesito intercambiar datos de matriz primitivos en mi caso. ¡Gracias! –

+0

@ JesúsZazueta, si solo se trata de una serie de elementos primitivos, probablemente usaría la interfaz de matrices JNI para hacerlo y tomar el golpe en una copia o dos. (O vuelva a trabajar el código para que pueda usar un búfer prestado de Java y compartir la misma memoria). – Flexo

Cuestiones relacionadas