简体   繁体   中英

Array of structures in a structure in JNA

My native code is

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

In Java my class looks like this

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()...
}

The method declaration is

int getDriverConfig(DriverConfig driverConfig);

I tried to access the method like this

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

If channel.length is replaced with less then 50 the array is initialized correctly but with channel.length it did not work. It even did not show any error just nothing.

Your getFieldOrder() array does not include the last element ( channel ) of your structure. I see in your comments that you attempted to do this but received an error because you have not declared it public . All elements of your structure must be listed in the FieldOrder and also declared public so they can be found with reflection.

Also, with JNA 5.x (which you should be using) the @FieldOrder annotation is preferred.

You haven't identified the mapping for ChannelConfig , but your question title and this API link matching your structure indicate that it is a nested structure array. Structure arrays must be allocated using contiguous memory, either by directly allocating the native memory ( new Memory() ) which requires knowing the structure size, or by using Structure.toArray() . Allocating in a loop as you have done will end up with memory for each new structure allocated at possibly/probably non-contiguous locations in native memory. Given that you state that it appears to work for some values, you might be getting lucky with contiguous allocations, but your behavior is certainly undefined.

Your structure mapping should therefore be:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM