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]);
}
}
¿Está todavía en busca de una solución a esto? – Flexo
sí, todavía no sé cómo hacerlo – paleozogt
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