A 3rd party DLL have a function that expects a pointer to pointer to structure as argument:
__declspec(dllimport) int __stdcall
SegmentImages( unsigned char* imageData, int imageWidth, int imageHeight,
int* numOfFinger, SlapInfo** slapInfo, const char* outFilename );
It segments a "slap" image of numOfFinger fingerprints (usually 4) into individual fingerprints (outFilename + number of finger).
The definition of SlapInfo is:
struct SlapInfo {
int fingerType;
Point fingerPosition[4];
int imageQuality;
int rotation;
int reserved[3];
};
struct Point {
int x;
int y;
};
A snippet of the example in C:
unsigned char* imageData;
int imageWidth, imageHeight;
//obtain imageData, imageWidth and imageHeight from scanner...
int numOfFinger;
SlapInfo* slapInfo;
int result = SegmentImages( imageData, imageWidth, imageHeight, &numOfFinger,
&slapInfo, FINGER_IMG_PATH);
JNA
According to JNA FAQ, In my case I should use "Structure.ByReference[]":
void myfunc(simplestruct** data_array, int count); // use Structure.ByReference[]
So, I mapped in Java/JNA like this:
Structures
public class Point extends Structure {
public int x;
public int y;
public Point(){
super();
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("x", "y");
}
}
public class SlapInfo extends Structure {
public int fingerType;
public Point[] fingerPosition = new Point[4];
public int imageQuality;
public int rotation;
public int[] reserved = new int[3];
public SlapInfo() {
super();
}
public SlapInfo(Pointer pointer){
super(pointer);
}
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("fingerType", "fingerPosition", "imageQuality",
"rotation", "reserved");
}
public static class ByReference extends SlapInfo implements Structure.ByReference { }
}
Function
int SegmentImages(byte[] imageData, int imageWidth, int imageHeight,
IntByReference numOfFinger, SlapInfo.ByReference[] slapInfo,
String outFileName);
Usage
//imageData, width and height are with valid values
IntByReference nrOfFingers = new IntByReference();
SlapInfo.ByReference[] slapInfoArray = (SlapInfo.ByReference[])
new SlapInfo.ByReference().toArray(4);
//Usually, there are 4 fingers in a slap, but the correct
//value should be the returned in nrOfFingers
int result = lib.SegmentImages(imageData, width, height,
nrOfFingers, slapInfoArray, FINGER_IMG_PATH);
But with this method, I get the error:
java.lang.Error: Invalid memory access
at com.sun.jna.Native.invokeInt(Native Method)
at com.sun.jna.Function.invoke(Function.java:419)
at com.sun.jna.Function.invoke(Function.java:354)
at com.sun.jna.Library$Handler.invoke(Library.java:244)
at com.sun.proxy.$Proxy0.SegmentImages(Unknown Source)
at scanners.JNAScanner.segmentToFile(JNAScanner.java:366)
I also tried with:
- PointerByReference instead of SlapInfo.ByReference[] (as explained in Pointer to array of structures as JNA method arguments)
- A "Pointer" class, as explained in JNA: pointers to array of pointers
- SlapInfo[] (only to try)
In all the cases, I got the error "Invalid memory access".
What am I doing wrong?