2009-09-16 13 views
7

Non ho molta familiarità con C, ma ho bisogno di usare una libreria C nel mio codice java. Ho creato la DLL e sono in grado di accedervi bene, ma sto tentando di restituire una serie di ints dal codice C al codice java.Ritorno dell'array C a Java usando JNA

In C, ho pensato che si potesse semplicemente restituire un puntatore all'array, ma non funziona come mi aspetto nel mio codice Java. Ecco il codice 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; 
} 

Se provo questo in C++ facendo

int* xy = getConusXY(33.92, -84.33); 
cout << xy[0] << " " << xy[1] << endl; 

allora funziona bene e ottengo i valori 739, 255 come previsto.

cerco di usarlo in Java con il pacchetto JNA in questo modo (ma questo mi dà 739, -16.777.214):

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

Nella documentazione JNA si dice array primitivi come int *buf sarebbero mappati int[] buf in Java, ma quando provo a modificare il tipo di ritorno da IntByReference a int[], viene visualizzata un'eccezioneArgument illegale.

Non so se sto restituendo l'array correttamente da C o se semplicemente non sto accedendo correttamente in Java. Qualsiasi aiuto sarebbe apprezzato.

risposta

4

non vorrei utilizzare tale funzione, perché la matrice restituita non verrà mai liberata/cancellato. avrei preferito modificare la funzione C se posso a:

void myFunc(Pointer resuls, int numBytes, byte const * returnArray)

6

Il codice C va bene dovrebbe essere migliore (vedere altri commenti), tuttavia, il problema principale è che stavo abusando del metodo java getInt() per il puntatore. Sembra che avrei dovuto usare lo getIntArray().

3

La spiegazione più lunga e forse più evidente è che si prototipi la funzione Java per ricevere puntatore (o un successore di Pointer) -

byte[] myFunc(Pointer result, int numBytes); 

Quando si crea la richiamata in sé, si utilizza getByteArray (int), o uno degli altri getArray.

byte[] myFunc(Pointer resuls, int numBytes) 
{ 
    return Pointer.getByteArray(numBytes); 
}