为什么我的JNA结构映射产生奇怪的字段值

Why does my JNA Structure mapping produce strange field values?

本文关键字:字段 我的 JNA 结构 映射 为什么      更新时间:2023-10-16

我正试图从Mathlab生成的dll调用函数。它似乎可以在C中工作,但当我尝试使用jna时,它会返回奇怪的结果。

我正在尝试用以下签名调用函数:

emxArray_real32_T *emxCreate_real32_T(int rows, int cols);

的结构为:

struct emxArray_real32_T
{
    float *data;
    int *size;
    int allocatedSize;
    int numDimensions;
    boolean_T canFreeData;
};

结构体在java中映射为:

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

,我用

LibSoftEdge libM = (LibSoftEdge) Native.loadLibrary("libsoftedge", LibSoftEdge.class);
LibSoftEdge.emxArray_real32_T  test; 
test =     libM.emxCreate_real32_T(3,3);

在测试对象中,我得到奇怪的值和空指针。

当您像这样返回字段顺序时:

@Override
protected List getFieldOrder() {
    return Arrays.asList("allocatedSize","canFreeData", "data","numDimensions","size");
}

您正在告诉JNA您的本地struct看起来像这样:

struct emxArray_real32_T
{
    int allocatedSize; // actually 'data'
    boolean_T canFreeData; // actually 'size'
    float *data; // actually 'allocatedSize'
    int numDimensions; 
    int *size; // actually 'canFreeData'
};

因此,当JNA在Java端填充字段时,您的值将是不正确的,因为您实质上打乱了您的字段。

此外,根据boolean_T的大小,您也可能会读取不对齐的数据,甚至可能最终导致崩溃。

你的getFieldOrder()应该是这样的:

@Override
protected List getFieldOrder() {
    return Arrays.asList("data", "size", "allocatedSize", "numDimensions", "canFreeData");
}

最后,如果您想为boolean_T使用Java boolean,而boolean_T的大小不是4个字节,那么您需要使用TypeMapper来确保正确转换类型。