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?
__stdcallin the C function declaration - your library is not using the cdecl calling convention. Does your library interface extendStdCallLibrary? - cbrslapInfoArray? But then again, the C example allocates just a pointer suggesting that the function may be replacing the pointer with an array it allocates itself. It's next to impossible to throw guesses at what may be going wrong without access to the library or its documentation. - cbr