2011-09-16 20 views
5

que tienen una función C de esta manera:devuelve una matriz de C a Java con TRAGO

void get_data(const obj_t *obj, short const **data, int *data_len); 

lo escribí como esto específicamente para trago, ya que

const short *get_data(const obj_t *obj, int *data_len); 

causas problemas, como typemaps de SWIG no son lo suficientemente inteligentes como para asociar el data_len con el valor de retorno.

En Java Quiero ser capaz de llamar a esta función como esta:

short data[]= mylib.get_data(obj); 

pero no puedo encontrar la manera de obtener el parámetro de salida del conjunto se convierta en un valor de retorno. Con Ruby y Python, esto funciona bien, ya que SWIG para esos idiomas admite devolver parámetros de salida como valores de retorno (ya que los idiomas pueden tener múltiples valores de retorno).

¿Cómo puedo hacer que funcione con Java?

+0

¿Está todavía en busca de una solución a esto? – Flexo

+0

sí, todavía no sé cómo hacerlo – paleozogt

+0

He respondido con una respuesta que coincide exactamente con la sintaxis de Java que solicitó. Sin embargo, hay una manera posible de responder con la función C original, si puede consultar el tamaño sin llenar la matriz. Agregaré eso a mi respuesta si estás interesado. – Flexo

Respuesta

7

He creado el siguiente archivo de cabecera de prueba para demostrar el problema:

typedef struct { } obj_t; 

const short *get_data(const obj_t *obj, int *data_len) { 
    (void)obj; 
    static short arr[] = {1,2,3,4,5}; 
    *data_len = sizeof(arr)/sizeof(*arr); 
    return arr; 
} 

Voy a hablar a través del archivo de módulo que escribí, que comienza bastante estándar:

%module test 

%{ 
#include "test.h" 
%} 

Entonces configuramos un mapa de tipos para el argumento data_len. No es necesario que esté visible en el lado de Java, ya que la longitud será conocida por la matriz, pero debemos organizar el almacenamiento para que apunte y nos aseguraremos de que dure lo suficiente para que podamos leerlo más tarde. al devolver la matriz a Java también.

%typemap(in,numinputs=0,noblock=1) int *data_len { 
    int temp_len; 
    $1 = &temp_len; 
} 

entonces queremos TRAGO utilizar short[] en el lado de Java para el tipo de retorno:

%typemap(jstype) const short *get_data "short[]" 
%typemap(jtype) const short *get_data "short[]" 

y jshortArray en el lado JNI - no hay necesidad de construir un tipo de proxy, por lo que sólo tiene que pasar el valor devuelto directamente a través de:

%typemap(jni) const short *get_data "jshortArray" 
%typemap(javaout) const short *get_data { 
    return $jnicall; 
} 

Finalmente creamos un typemap que va a crear una nueva matriz, con un tamaño basado en la longitud de regresar de la diversión ction y copie el resultado devuelto en la matriz de Java para nosotros. Si es necesario, debemos free() el conjunto de resultados real aquí, pero en mi ejemplo se asignó estáticamente por lo que no necesitaba ser liberado.

%typemap(out) const short *get_data { 
    $result = JCALL1(NewShortArray, jenv, temp_len); 
    JCALL4(SetShortArrayRegion, jenv, $result, 0, temp_len, $1); 
    // If the result was malloc()'d free it here 
} 

Por último se incluye el archivo de cabecera para TRAGO para envolver, utilizando los typemaps que acaba de escribir:

%include "test.h" 

He probado esto con:

public class run { 
    public static void main(String argv[]) { 
    System.loadLibrary("test"); 
    obj_t obj = new obj_t(); 
    short[] result = test.get_data(obj); 
    for (int i = 0; i < result.length; ++i) { 
     System.out.println(result[i]); 
    } 
    } 
} 

que produjo:

 
1 
2 
3 
4 
5 

Para tener una referencia que podría haber envuelto:

void get_data(const obj_t *obj, short const **data, int *data_len); 

también, aunque si su función tenía una forma de consultar el tamaño sin ajustar la gama que podría terminar con esto un poco más inteligente mediante la asignación de una matriz del tamaño correcto en el Java lado. Para hacer esto, querrá escribir una función intermedia en Java que consultó el tamaño, configuró la llamada y luego devolvió la matriz resultante. Esto le permitiría usar GetShortArrayElements/ReleaseShortArrayElements para una llamada de copia potencialmente 0.

Esto funcionaría porque las matrices en Java son básicamente pasan por referencia, por ejemplo .:

public class ret { 
    public static void foo(int arr[]) { 
    arr[0] = -100; 
    } 

    public static void main(String argv[]) { 
    int arr[] = new int[10]; 
    System.out.println(arr[0]); 
    foo(arr); 
    System.out.println(arr[0]); 
    } 
} 
+2

Para mayor comodidad, el archivo de interfaz completo que utilicé para probar está en mi sitio en: http://static.lislan.org.uk/~ajw/javaarrout.i - si ese enlace se rompe, la respuesta no pierde nada porque puede ser reproducido de la respuesta misma. – Flexo

Cuestiones relacionadas