Devolviendo la matriz C a Java usando JNA
Pregunta
No estoy muy familiarizado con C, pero necesito usar una biblioteca C en mi código Java. He creado la DLL y puedo acceder a ella perfectamente, pero estoy intentando devolver una serie de entradas del código C al código Java.
En C pensé que simplemente podría devolver un puntero a la matriz, pero no funciona como esperaba en mi código Java. Aquí está el código C:
int * getConusXY(double latitude, double longitude) {
maparam stcprm;
double reflat = 25, reflon = -95,
lat1 = 20.191999, lon1 = -121.54001,
x1 = 0, y1 = 0, x2 = 1073, y2 = 689,
gsize = 5.079, scaLat = 25, scaLon = -95, orient = 0;
double x, y;
int* xy;
xy = malloc(2 * sizeof *xy);
stlmbr(&stcprm, reflat, reflon);
stcm1p(&stcprm, x1, y1, lat1, lon1, scaLat, scaLon, gsize, orient);
cll2xy(&stcprm, latitude, longitude, &x, &y);
xy[0] = (int) x;
xy[1] = (int) y;
return xy;
}
Si pruebo esto en C ++ haciendo
int* xy = getConusXY(33.92, -84.33);
cout << xy[0] << " " << xy[1] << endl;
entonces funciona bien y obtengo los valores 739, 255 como se esperaba.
Intento usarlo en Java con el paquete JNA así (pero esto me da 739, -16777214):
public class DmapFDllLibrary {
interface DmapFLibrary extends Library {
DmapFLibrary INSTANCE = (DmapFLibrary) Native.loadLibrary("DmapFDll",
DmapFLibrary.class);
IntByReference getConusXY(double latitude, double longitude);
}
public static void main(String... strings) {
IntByReference xy_ref = DmapFLibrary.INSTANCE.getConusXY(33.92, -84.33);
Pointer p = xy_ref.getPointer();
System.out.println(p.getInt(0) + " " + p.getInt(1));
}
}
En la documentación de JNA dice que las matrices primitivas como int * buf
se asignarían a int [] buf
en Java, pero cuando intento cambiar el tipo de retorno de IntByReference
a int []
y obtengo una excepción de argumento ilegal.
No sé si estoy devolviendo la matriz correctamente desde C o si simplemente no estoy accediendo a ella correctamente en Java. Cualquier ayuda sería apreciada.
Solución
No usaría dicha función, porque la matriz devuelta nunca será liberada / eliminada. Prefiero cambiar la función C si puedo:
void myFunc (resultados del puntero, int numBytes, byte const * returnArray)
Otros consejos
El código C está bien debería ser mejor (ver otros comentarios), sin embargo, el problema principal es que estaba usando mal el método java getInt ()
para el puntero . Parece que debería haber estado usando el getIntArray ()
.
La explicación más larga y quizás más clara es que prototipa su función Java para recibir Pointer (o un sucesor de Pointer) -
byte[] myFunc(Pointer result, int numBytes);
Al crear la devolución de llamada en sí, usa getByteArray (int), o uno de los otros getArrays.
byte[] myFunc(Pointer resuls, int numBytes)
{
return Pointer.getByteArray(numBytes);
}