JNA 结构中的结构数组

Array of structures in a structure in JNA

我的本机代码是

typedef struct driver_config {
    unsigned int dllVersion;
    unsigned int channelCount;
    unsigned int reserved[10];
    ChannelConfig channel[64];
} DriverConfig;

在 Java 我的 class 看起来像这样

public class DriverConfig extends Structure {
    
    public int dllVersion;
    public int channelCount;
    public int[] reserved= new int[10];
    ChannelConfig[] channel = new ChannelConfig[64];
    
    public DriverConfig() {
        super();
        init();     
    }
    
    private void init() {
        for (int i = 0; i < channel.length; i++) {
            channel[i]= new ChannelConfig();
        }
    }

    @Override
    protected List<String> getFieldOrder() {
        return Arrays.asList(new String[] { "dllVersion", "channelCount", "reserved" });
    }

    //toString()...
}

方法声明为

int getDriverConfig(DriverConfig driverConfig);

我试过这样访问方法

DriverConfig driverConfig = new DriverConfig();
status = dll.INSTANCE.getDriverConfig(driverConfig);
System.out.println("DriverConfig Status: " + status);
System.out.println(driverConfig.toString());

如果 channel.length 被替换为小于 50 的数组被正确初始化,但是 channel.length 它没有工作。它甚至没有显示任何错误。

您的 getFieldOrder() 数组不包含结构的最后一个元素 (channel)。我在你的评论中看到你试图这样做但收到错误,因为你没有声明它 public。您的结构的所有元素都必须在 FieldOrder 中列出并声明 public 以便可以通过反射找到它们。

此外,对于 JNA 5.x(您应该使用),@FieldOrder 注释是首选。

您尚未确定 ChannelConfig 的映射,但您的问题标题和 this API link matching your structure 表明它是一个嵌套结构数组。必须使用连续内存分配结构数组,方法是直接分配需要知道结构大小的本机内存 (new Memory()),或者使用 Structure.toArray()。像您所做的那样在循环中分配最终会为在本机内存中 possibly/probably non-contiguous 位置分配的每个新结构分配内存。鉴于您声明它似乎适用于某些值,您可能对连续分配感到幸运,但您的行为肯定是未定义的。

因此您的结构映射应该是:

@FieldOrder ({"dllVersion", "channelCount", "reserved", "channel"})
public class DriverConfig extends Structure {
    public int dllVersion;
    public int channelCount;
    public int[] reserved= new int[10];
    public ChannelConfig[] channel = (ChannelConfig[]) new ChannelConfig().toArray(64);
}