Pregunta std :: vector to java.util.Vector generación de código con swig


Intento generar código Java con SWIG

En MyList.h Decidí un objeto de lista personalizado llamado _lista

List<T*> _list;

y esta clase List hereda del vector

class List : public vector<T>

En una clase de negocios (en C ++) devuelvo una Lista de objetos personalizados

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

así que quiero generar código java donde pueda recuperar esta lista de C ++ como java.util.List o java.util.Vector.

en mi archivo swig.i no pude manejar cómo encarnar

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

De cualquier modo, se apreciará cómo configurar este archivo de plantilla swig.i o algún código de muestra para generar una función de retorno java.util.List / Vector.

Gracias.


7
2018-05-15 07:26


origen


Respuestas:


Realmente no quieres tocar java.util.Vector con sus interfaces envolventes porque terminará duplicando el almacenamiento o haciendo un gran número de operaciones de copiado cada vez que lo ingresa o retira 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 respuesta anterior a una pregunta similar.

Funciona para todos std::vector tipos, no solo un tipo fijo y maneja primitivas a las que se debe acceder mediante Objetos usando un mapa de tipo personalizado "autobox". Falta soporte para el servicio especializado std::vector<bool>, pero eso debería ser simple de agregar si lo necesitas.

%{
#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);
    }
  }
%}

La mayoría de esto es bastante similar al std_vector.i predeterminado que SWIG proporciona actualmente, los nuevos bits son el renombrado, la extensión y los mapas de tipos que se extienden AbstractList e implementar RandomAccess. También agrega un constructor que toma otro Collections - esto es recomendado por la documentación de Java y lo suficientemente fácil de hacer. (Hay una sobrecarga para otros std::vector tipos que es mucho Más rápido).

Probé este vector envolviendo 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>;

Con lo que pude compilar y ejecutar:

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);
    }
  }
}

10
2017-09-23 09:18