javajnajnaerator

How to map variable length arrays in a structured returned from a native method using JNA


I have a structure that contains an array of other structure pointers, along with a field for the array length. This structure is returned via an "out" parameter by a native method.

The original "C" structure:

typedef struct MMAL_COMPONENT_T
{
    uint32_t    input_num;   /**< Number of input ports */
    MMAL_PORT_T **input;     /**< Array of input ports */
} MMAL_COMPONENT_T;

The corresponding Java class generated by JNAerator:

public class MMAL_COMPONENT_T extends Structure {
    public int input_num;
    public MMAL_PORT_T.ByReference[] input;
}

The "C" method signature:

MMAL_STATUS_T mmal_component_create(const char *name, MMAL_COMPONENT_T **component);

Java usage:

PointerByReference ref = new PointerByReference();
status = mmal.mmal_component_create("<component-name>", ref);
MMAL_COMPONENT_T component = new MMAL_COMPONENT_T(ref.getValue());

This generates a JNA error message stating that "Array fields must be initialized".

Currently I am using Pointer in place of the array and manually building the array from it:

public class MMAL_COMPONENT_T extends Structure {
    public int input_num;
    public Pointer input;
}

With usage:

Pointer[] array = component.input.getPointerArray(0, component.input_num);
MMAL_PORT_T port = new MMAL_PORT_T(array[0]);
port.read();

But this approach seems unsatisfactory because of its verbosity and because Pointer is used rather than the actual structure type.

So what is the canonical way to handle this with JNA?


Solution

  • Assuming input points to an array of pointers, encapsulate the Pointer manipulation in a member function, e.g.

    public MMAL_PORT_T[] getPorts() {
        Pointer[] array = input.getPointerArray(0, input_num);
        MMAL_PORT_T[] ports = new MMAL_PORT_T[array.length];
        for (int i=0;i < ports.length;i++) {
            ports[i] = new MMAL_PORT_T(array[i]);
        }
        return ports;
    }