java-ffm

How do you create a StructLayout for a native C structure that is recursive using the Java FFM API


I have a MemoryLayout like this:

public class TestStruct {
  private static final MemoryLayout layout = MemoryLayout.structLayout(
    JAVA_INT.withName("i_one_thing"),
    JAVA_INT.withName("i_another_thing"),
    ADDRESS.withName("p_next")
  );
}

The p_next field is a pointer to another instance of this exact same layout, and links these structures until the pointer value becomes NULL.

I want to avoid as much as possible using memorySegment.reinterpret() calls when using such structures, so I want to do something like this:

public class TestStruct {
  private static final MemoryLayout layout = MemoryLayout.structLayout(
    JAVA_INT.withName("i_one_thing"),
    JAVA_INT.withName("i_another_thing"),
    ADDRESS.withName("p_next").withTargetLayout(TestStruct.layout)
  );
}

But obviously this will not work since the layout field has not yet been initialised and so is null.

Is there an idiomatic way to do this using the Java FFM API?


Solution

  • withTargetLayout is essentially the 'static' form of reinterpret, for cases when the target layout is known upon construction. But, that is not (quite) the case here, as the layout is recursive.

    You could either use reinterpret in this case, or another option is to create a second, 'shallow' layout that is used as a target:

    private static final MemoryLayout LAYOUT = MemoryLayout.structLayout(
        JAVA_INT.withName("i_one_thing"),
        JAVA_INT.withName("i_another_thing"),
        ADDRESS.withName("p_next")
            .withTargetLayout(MemoryLayout.structLayout(
                JAVA_INT,
                JAVA_INT,
                ADDRESS
            ))
    );
    

    This works just as well in most cases, since only the size and alignment of the target layout is used when reading the pointer from the struct.