2012-05-15 9 views
6

provo a generare il codice Java con SWIGstd :: vector a java.util.Vector generazione di codice con sorso

In MyList.h ho dichiarato un oggetto di elenco personalizzato chiamato _list

List<T*> _list; 

e questo elenco classe eredita da vettore

class List : public vector<T> 

in un business class (in C++) torno a Li st di oggetti personalizzati

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

quindi voglio generare il codice Java in cui posso recuperare questo elenco C++ come java.util.List o java.util.Vector.

nel mio file swig.i non ho potuto gestire il modo di incarnare

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

qualsiasi tipo di aiuto come configurare questo file modello swig.i o qualche codice di esempio per generare un java.util.List/La funzione di ritorno del vettore sarà apprezzata.

Grazie.

+0

prega di dare un'occhiata al http: // StackOverflow.com/domande/1854335/how-to-create-a-java-class-simile-a-ac-template-class e http://stackoverflow.com/questions/462297/how- to-use-classt-in-java – phantasmagoria

+2

Riguardo all'eredità 'std :: vector', dai un'occhiata a [questa domanda] (http://stackoverflow.com/questions/4353203/thou-shalt-not-inherit-da -stdvector). – juanchopanza

+0

OK diciamo che non userò/restituirò un vettore std :: come posso trasferire un elenco di oggetti dal livello C++ al mio livello java. –

risposta

10

Non si desidera realmente toccare java.util.Vector con le interfacce avvolte perché si finirà per duplicare la memoria o effettuare un gran numero di operazioni di copia ogni volta che si passa dentro o fuori una funzione. (Si noti inoltre che in generale in C++ ereditato dai contenitori è un disegno strano).

Invece in Java la cosa "giusta" da fare è ereditare da java.util.AbstractList. Questa risposta è una versione più generica del mio older answer to a similar question.

Funziona con tutti i tipi std::vector, non solo un tipo fisso e gestisce primitives which need to be accessed via Objects utilizzando una mappa di tipo personalizzato "Autobox". Manca il supporto per lo specialista std::vector<bool>, ma dovrebbe essere semplice da aggiungere se ne hai bisogno.

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

maggior parte di questo è abbastanza simile alla std_vector.i predefinito SWIG fornisce attualmente, i nuovi bit sono la ridenominazione, estendendo e typemaps che si estendono AbstractList e implementano RandomAccess. Aggiunge anche un costruttore che prende altri Collection s - questo è raccomandato dalla documentazione Java e abbastanza facile da fare. (C'è un sovraccarico per altri tipi di std::vector che è molto più veloce).

Ho provato questo wrapping all'interno di un'altra interfaccia 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>; 

Quali sono stato in grado di compilare ed eseguire 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

(Testato con SWIG 2.0.4) – Flexo

+0

Ciao. Consiglieresti comunque di utilizzare questo wrapper invece dell'implementazione 'std_vector.i' di SWIG? Ho solo bisogno di scambiare dati di array primitivi nel mio caso. Grazie! –

+0

@ JesúsZazueta se si tratta solo di una serie di primitive, probabilmente utilizzerei l'interfaccia degli array JNI per farlo e prendere il colpo su una o due copie. (Oppure rielaborare il codice in modo che possa utilizzare un buffer preso in prestito da Java e condividere la stessa memoria). – Flexo

Problemi correlati