Quello che hai fatto qui con array_functions
è corretto e utilizzabile, ma è incentrato sul wrapping del codice C++ direttamente e non utilizzerà un array Java sottostante. Si può usare con qualcosa di simile:
SWIGTYPE_p_long_long array = MyLib.new_long_long_array(100); // new array with 100 elements.
for (int i = 0; i < 100; ++i) {
long_long_array_setitem(array, i, i);
}
new Test().SelectValues(array);
dove array è solo un proxy per un "vero" C++ pezzo di memoria che si può leggere/scrivere dal lato Java e passare alle funzioni avvolti.
Sto supponendo dalla tua domanda che sei interessato a farlo sentire più "naturale" sul lato Java. SWIG fornisce anche array_class
che avvolge un array in modo simile, ma come un oggetto appropriato piuttosto che una raccolta di funzioni statiche. Per esempio se è stato modificato il file interfaccia da utilizzare al posto di array_class(long long, LongLongArray)
array_functions
si può fare:
LongLongArray array = new LongLongArray(100);
for (int i = 0; i < 100; ++i) {
array.setitem(i,i);
}
new Test().SelectValues(array.cast());
Si può effettivamente fare SWIG fare di più con pochi typemaps se si vuole. La tua classe di esempio non prende una lunghezza in SelectValues
quindi suppongo che tu stia terminando la matrice 0, sebbene tu possa ugualmente superare la lunghezza con alcune semplici modifiche.
(Per comodità ho %inline
D tua classe per ridurre il numero di file e ha aggiunto un'implementazione manichino di esso per le prove)
%module MyLib
%{
#include <iostream>
%}
%typemap(jtype) long long values[] "long[]"
%typemap(jstype) long long values[] "long[]"
%typemap(javain) long long values[] "$javainput"
%typemap(jni) long long values[] "jlongArray"
%typemap(in) long long values[] {
jboolean isCopy;
$1 = JCALL2(GetLongArrayElements, jenv, $input, &isCopy);
}
%inline %{
class Test
{
public:
void SelectValues(long long values[]) {
while (*values) {
std::cout << *values++ << "\n";
}
}
};
%}
Qui abbiamo detto che sia lo SWIG classe proxy genera e la classe JNI esso genererà sta funzionando con long[]
, cioè una matrice Java. Non abbiamo bisogno di fare nulla nella conversione da Java Proxy a Java JNI, quindi la typemap javain
è solo un passaggio dritto. Sul lato C++ del JNI è un jlongArray
, che abbiamo anche specificato in un'altra typemap.
Abbiamo poi bisogno di un in
typemap di organizzare la conversione da jlongArray a long long[]
nella parte C++ - c'è una sola chiamata JNI per questo e non ci importa se si tratta di una copia o la memoria reale dalla JVM che finiamo utilizzando.(Si potrebbe preoccuparsi se si voleva modificare i risultati e rendere più visibile di nuovo dentro Java per esempio)
Ho provato questo con:
public class run {
public static void main(String[] argv) {
System.loadLibrary("mylib");
long arr[] = {100,99,1,0}; // Terminate with 0!
new Test().SelectValues(arr);
}
}
Il che ha fatto esattamente come ci si spera.
il 'jlong' che hai visto sul lato JNI è come SWIG avvolge tutto ciò che non è un tipo primitivo. – Flexo