JNA and array of Structure as parameter

1.3k views Asked by At

i'm access SocketCAN with JNA. But I have problems with the setsockopt function.

The declaration of the function:

int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

SocketCAN use following structure:

struct can_filter {
            canid_t can_id;
            canid_t can_mask;
    };

It is possbile to set one filter with one can_filter structure as parameter or several with an array of the can_filter structure.

Example from SocketCAN docu:

    struct can_filter rfilter[2];

    rfilter[0].can_id   = 0x123;
    rfilter[0].can_mask = CAN_SFF_MASK;
    rfilter[1].can_id   = 0x200;
    rfilter[1].can_mask = 0x700;

    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

If I define the function for one structure as parameter in JNA then it runs without problems:

private static native int setsockopt(int sockfd, int level, int option_name, CanFilterStruct filter, int len);

If I define the function for an array of structures then I get an error at init:

private static native int setsockopt(int sockfd, int level, int option_name, CanFilterStruct[] filters, int len);

The occuring error:

Exception in thread "main" java.lang.ExceptionInInitializerError
    at de.comp.test.App.main(App.java:42)
Caused by: java.lang.IllegalArgumentException: class [Lde.comp.jsocketcan.CanFilterStruct; is not a supported argument type (in method setsockopt in class de.comp.jsocketcan.SocketCan)
    at com.sun.jna.Native.register(Native.java:1463)
    at com.sun.jna.Native.register(Native.java:1396)
    at com.sun.jna.Native.register(Native.java:1156)
    at de.comp.jsocketcan.SocketCan.<clinit>(SocketCan.java:70)

Here the definition of the structure in JNA:

public class CanFilterStruct extends Structure implements Structure.ByReference
{
    public int can_id;
    public int can_mask;

    public CanFilterStruct()
    {
        super();
    }

    @Override
    protected List getFieldOrder() 
    {
        return Arrays.asList("can_id", "can_mask");
    }
}

Can some one help me?

Best regards

1

There are 1 answers

1
technomage On

Use Structure.toArray() to obtain a contiguously-allocated block of structures, then pass in the first element.

EDIT

Your parameter type is still CanFilterStruct.

Explicitly:

CanFilterStruct s = new CanFilterStruct();
CanFilterStruct[] array = (CanFilterStruct[])s.toArray(length);

lib.setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, array[0], array.length * array[0].size());