2010-11-12 13 views
7

Ho un metodo in C++ che accetta una serie di doppi come argomento. Sto chiamando questo metodo da Java e ho bisogno di passare una serie di doppi. La routine C++ legge e modifica i valori dell'array e ho bisogno di quei valori aggiornati in Java. Come faccio a fare questo?Come faccio a passare gli array da Java a C++ usando Swig?

Per esempio, prendete il C++ di routine:

void myMethod(double *values, int size) { 
    for (int i=0; i < size; i++) { 
     values[i] = 2*values[i]; 
    } 
} 

E il codice Java:

double[] values = { 1.3, 1.1 }; 
myMethod(values,values.length); 
System.out.println(values[0]); // prints 2.6 

Credo che una chiamata a myMethod non può essere fatto come la chiamata di cui sopra ... o può ? E ciò che è necessario in Swig per farlo funzionare. Se non riesco a effettuare una chiamata come quella sopra, come posso ottenere i miei valori sul codice C++?

+1

La risposta è SWIG. Il resto delle risposte discute le alternative. –

+0

Sì, grazie mille Andy! Capisci la mia domanda e hai dato una risposta molto appropriata ... Sono ancora alla ricerca di ulteriori risposte. Sono particolarmente interessato a ciò che fa la maggior parte delle persone, poiché questa situazione deve emergere in ogni momento. La maggior parte delle persone usa Swig 2? La maggior parte delle persone scrive i propri typemaps? Entrambi mi sembrano estremi. – Jason

+0

Se devo copiare manualmente la matrice in C++ va bene. Se posso allocare un array in C++ e devo usare metodi speciali per accedere ai valori in Java, va bene. Cosa fa la maggior parte della gente in casi come questo? – Jason

risposta

6

Usa carrays.i!

Vedi Swig docs on carrays

%include carrays.i 
%array_functions(double, double_array) 

Queste due linee creano il seguente codice nel mio modulo:

public static SWIGTYPE_p_double new_double_array(int nelements) { 
    long cPtr = SimulatorModuleJNI.new_double_array(nelements); 
    return (cPtr == 0) ? null : new SWIGTYPE_p_double(cPtr, false); 
    } 

    public static void delete_double_array(SWIGTYPE_p_double ary) { 
    SimulatorModuleJNI.delete_double_array(SWIGTYPE_p_double.getCPtr(ary)); 
    } 

    public static double double_array_getitem(SWIGTYPE_p_double ary, int index) { 
    return SimulatorModuleJNI.double_array_getitem(SWIGTYPE_p_double.getCPtr(ary), index); 
    } 

    public static void double_array_setitem(SWIGTYPE_p_double ary, int index, double value) { 
    SimulatorModuleJNI.double_array_setitem(SWIGTYPE_p_double.getCPtr(ary), index, value); 
    } 

Il che mi permette di usare gli array in Java C ... questo risolve le mie esigenze ed è la migliore soluzione per il mio problema. Grazie a tutti per le vostre risposte!

+0

Grazie per aver postato un approccio più semplice. Penso che dovresti accettare la tua risposta. Il collegamento SWIG 2.0 per i carri è disponibile all'indirizzo http://www.swig.org/Doc2.0/SWIGDocumentation.html#Library_carrays. –

+0

È questo il modo più veloce? Suppongo che sia necessario chiamare SWIGTYPE_p_double con il numero di elementi nel proprio array Java, quindi copiare ciascun elemento nel nuovo array, quindi eseguire l'elaborazione in C++ sul nuovo array, quindi copiare ciascun elemento nuovamente nell'array Java. C'è un modo per fare l'accesso diretto alla memoria e basta passare un puntatore tra le due lingue? Oppure queste operazioni di copia extra sono l'unico modo per farlo a causa della differenza nella gestione della memoria tra Java e Cxx? – LaserJesus

0

Supponendo che non si può fare quello che suggerisce org.life.java ...

È possibile controllare IPC's e anche i file.

Un'altra cosa che puoi fare è creare un processo passandogli il percorso dell'exe contenente il codice C++ e l'array come argomento. [Runtime.exec (java.lang.String, java.lang.String [])] [2] dovrebbe essere in grado di farlo.

[2]: http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Runtime.html#exec(java.lang.String, java.lang.String [])

0

Se è solo questo singolo metodo, riscriverlo. Se hai una base di codice C++ (molto più grande) che devi portare, usa JNI (o il più semplice JNA). Questo aggiunge un bel po 'di overhead del codice, ma è fattibile.

+0

Um ... è esattamente quello che sto facendo ... usando JNI perché è una grande base di codice. Così ho scelto di usare Swig per creare i wrapper JNI ... visto che Swig è molto più semplice. – Jason

1

SWIG typemaps dovrebbe consentire questo. La documentazione SWIG 2.0 mostra questo example in Python.

Con Java, si utilizzerà il codice JNI all'interno della propria tipografia SWIG. JNI fornisce i metodi Get/ReleaseArrayElements. Immagino che potresti ottenere un array nativo in un typemap(in), quindi rilasciarlo in un typemap(argout).

Un altro approccio potrebbe essere quello di copiare la matrice in un vettore std :: utilizzando la typemap SWIG esistente in std_vector.i.

+0

Questa è un'ottima risposta! Grazie! Posso usare questa soluzione. Ma la prima parte (scrivendo la mia typemap) è complessa e la seconda parte richiede Swig 2. Al momento credo che ci sia una soluzione più semplice ... e non mi interessa scrivere del codice per copiare l'array in C. Ho intenzione di aggiornare le mie domande ... vedere l'aggiornamento in alto. – Jason

Problemi correlati