I am trying to call functions from a dll generated by Mathlab. It appears to work ok in C, but it returns weird results when i try to use jna.
I am trying to call the function with the following signature :
emxArray_real32_T *emxCreate_real32_T(int rows, int cols);
with the structure:
struct emxArray_real32_T
{
float *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
The structure is mapped in java to:
public interface LibSoftEdge extends StdCallLibrary {
public static class emxArray_real32_T extends Structure{
public Pointer data ;
public Pointer size;
public int numDimensions;
public int allocatedSize;
public boolean canFreeData;
@Override
protected List getFieldOrder() {
return Arrays.asList(new String[]{"allocatedSize","canFreeData",
"data","numDimensions","size"});
}
@Override
public String toString() {
return "emxArray_real32_T{" +
"data=" + data +
", size=" + size +
", allocatedSize=" + allocatedSize +
", numDimensions=" + numDimensions +
", canFreeData=" + canFreeData +
'}';
}
}
emxArray_real32_T emxCreate_real32_T(int rows, int cols);
}
and i call it with :
LibSoftEdge libM = (LibSoftEdge) Native.loadLibrary("libsoftedge", LibSoftEdge.class);
LibSoftEdge.emxArray_real32_T test;
test = libM.emxCreate_real32_T(3,3);
In the test object I get weird values and null pointers.
Any suggestion is much apreciated.
When you return your field order like this:
@Override
protected List getFieldOrder() {
return Arrays.asList("allocatedSize","canFreeData", "data","numDimensions","size");
}
You are telling JNA that your native struct
looks like this:
struct emxArray_real32_T
{
int allocatedSize; // actually 'data'
boolean_T canFreeData; // actually 'size'
float *data; // actually 'allocatedSize'
int numDimensions;
int *size; // actually 'canFreeData'
};
So when JNA populates the fields on the Java side, your values will be incorrect because you're essentially scrambling your fields.
In addition, depending on the size of boolean_T
, you might be reading misaligned data as well, and might even end up crashing.
Your getFieldOrder()
should look like this:
@Override
protected List getFieldOrder() {
return Arrays.asList("data", "size", "allocatedSize", "numDimensions", "canFreeData");
}
Finally, if you want to use Java boolean
for boolean_T
and boolean_T
is any size other than four bytes, then you'll need to use a TypeMapper
to ensure the types are converted properly.