2012-06-08 9 views
5

Tengo archivo .h muestra como a continuación:Cómo pasar matriz (array de tiempo en Java) de Java a C++ utilizando trago

class Test 
{ 
public: 
     void SelectValues(long long values[]) 
}; 

Solía ​​TRAGO y creé interfaz JNI desde abajo fichero .I

%module MyLib 
%include "carrays.i" 
%array_functions(long long, long_long_array) 


%{ 
    #include "Test.h" 
%} 

/* Let's just grab the original header file here */ 
%include <windows.i> /*This line is used for calling conventions*/ 
% include "Test.h" 

Cuando creo método Java se crea como:

public void SelectValues(SWIGTYPE_p_long_long includeKeys) 

también para presentar JNI que está tomando como argumento jlongArray pero tomando solo jlong solamente. Debido a este problema, no puedo crear una matriz de longitud como long[]={1L,2L} y pasarla al método Java anterior para llamar al método JNI apropiado.

Quiero que SWIG genere la interfaz de tal forma que pueda pasar la matriz mencionada anteriormente a mi método C++.

He leído this question, pero no me ayudó a ver cómo pasar una matriz de Java a C++.

+0

el 'jlong' que viste en el lado JNI es cómo SWIG envuelve todo lo que no es un tipo primitivo. – Flexo

Respuesta

2

Lo que ha hecho aquí con array_functions es correcto y utilizable, pero se centra en envolver directamente el código de C++ y no utilizará una matriz de Java subyacente. Se puede utilizar con algo como:

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

donde la matriz es sólo un proxy para un "verdadero" C++ trozo de memoria que se puede leer/escribir desde el lado de Java y pasar a las funciones envueltos.

Supongo por su pregunta que está interesado en hacer que esto se sienta más "natural" en el lado de Java. SWIG también proporciona array_class que envuelve una matriz de manera similar, pero como un objeto propio en lugar de una colección de funciones estáticas. Por ejemplo si ha cambiado el archivo de interfaz para utilizar array_class(long long, LongLongArray) en lugar de array_functions que puede hacer:

LongLongArray array = new LongLongArray(100); 
for (int i = 0; i < 100; ++i) { 
    array.setitem(i,i); 
} 
new Test().SelectValues(array.cast()); 

Usted puede hacer realmente TRAGO hacer más que eso con algunas typemaps si quieres. Tu clase de ejemplo no tiene una longitud en SelectValues, así que supongo que estás terminando la matriz 0 aunque también puedes pasar la longitud con unos pocos cambios simples.

(Por conveniencia %inline D Sus clase para reducir el número de archivos y ha añadido una aplicación simulada de la misma para la prueba)

%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"; 
    } 
    } 
}; 
%} 

Aquí hemos dicho que tanto el TRAGO clase proxy genera y la clase JNI se genera va a funcionar con long[], es decir, una matriz de Java. No necesitamos hacer nada en la conversión JNI de Java Proxy a Java, por lo que el mapa de tipos javain es solo un paso directo. En el lado C++ del JNI que es un jlongArray, que también especificamos en otro mapa de tipos.

entonces necesitamos un typemap in para organizar la conversión de jlongArray a long long[] en el lado de la C++ - no hay una sola llamada JNI para eso y no nos importa si se trata de una copia o la memoria real de la JVM que terminamos utilizando.(Es posible que cuidar si desea modificar los resultados y hacerla visible de nuevo dentro de Java por ejemplo)

He probado esto 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); 
    } 
} 

¿Qué hizo exactamente lo que usted esperaría.

+0

Si no desea utilizar 0 para terminar las matrices, deberá cambiar SelectValues ​​a algo como: 'void SelectValues ​​(long long values ​​[], size_t len);' - Puedo agregar eso a mi respuesta si querer. – Flexo

+0

Agregué ese ejemplo al final: http://stackoverflow.com/q/11584599/168175 – Flexo