tags:

views:

600

answers:

2

I am not too familiar with C, but I need to use a C library in my java code. I have created the DLL and am able to access it just fine, but I am attempting to return an array of ints from the C code to the java code.

In C I thought you could simply return a pointer to the array, but it's not working like I expect in my Java code. Here's the C code:

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

If I test this in C++ by doing

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

then it works fine and I get the values 739, 255 like expected.

I try using it in Java with the JNA package like so (but this gives me 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));

}
}

In the JNA documentation it says primitive arrays such as int *buf would be mapped to int[] buf in Java, but when I try changing the return type from IntByReference to int[] then I get an illegalArgumentException.

I don't know if I'm returning the array correctly from C or if I'm just not accessing it correctly in Java. Any help would be appreciated.

+1  A: 

The C code is fine, I was just misusing the java getInt() method for the pointer. It seems I should've been using the getIntArray().

ravun
A: 

The longer and perhaps more clear explanation is that you prototype your Java function to receive Pointer (or a successor of Pointer) -

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

When creating the callback itself, you use getByteArray(int), or one of the other getArrays.

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