Passing unaligned structs as function arguments

Manuel Bleichenbacher manuel.bleichenbacher at gmail.com
Thu May 1 18:07:23 UTC 2025


Hi Panama team,

This code calling a Windows API fails:

        try (var arena = Arena.ofConfined()) {
            var transfer = _WINUSB_SETUP_PACKET.allocate(arena);
            WinUsb.WinUsb_ControlTransfer(NULL, transfer, NULL, 0, NULL,
NULL);
        }

It throws an exception:

    Exception in thread "main" java.lang.ExceptionInInitializerError
        at org.example.gen.WinUsb.WinUsb_ControlTransfer(WinUsb.java:121)
        at org.example.App.main(App.java:53)
    Caused by: java.lang.IllegalArgumentException: Unsupported layout: 1%s2
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.checkSupported(AbstractLinker.java:293)
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.checkLayoutRecursive(AbstractLinker.java:186)
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.checkStructMember(AbstractLinker.java:181)
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.checkLayoutRecursive(AbstractLinker.java:196)
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.checkLayout(AbstractLinker.java:175)
        at java.base/java.lang.Iterable.forEach(Iterable.java:75)
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.checkLayouts(AbstractLinker.java:167)
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.downcallHandle0(AbstractLinker.java:97)
        at
java.base/jdk.internal.foreign.abi.AbstractLinker.downcallHandle(AbstractLinker.java:84)
        at
org.example.gen.WinUsb$WinUsb_ControlTransfer.<clinit>(WinUsb.java:82)
        ... 2 more

Both WinUsb_ControlTransfer() and _WINUSB_SETUP_PACKET have been generated
with jextract and are correct as far as I can tell.

Two aspects are special in this call:

   1.  _WINUSB_SETUP_PACKET is a packed struct with an alignment of 1 byte.
   2. _WINUSB_SETUP_PACKET is passed by value.

Is it a restriction of FFM that unaligned structs cannot be passed by value
(it works if the natural alignment of 2 bytes is used)? Or what is the
issue here?

For reference, here is the relevant jextract generated code:

WINUSB_SETUP_PACKET (
https://learn.microsoft.com/en-us/windows/win32/api/winusb/ns-winusb-winusb_setup_packet
):

    private static final GroupLayout $LAYOUT = MemoryLayout.structLayout(
        WinUsb.C_CHAR.withName("RequestType"),
        WinUsb.C_CHAR.withName("Request"),
        WinUsb.align(WinUsb.C_SHORT, 1).withName("Value"),
        WinUsb.align(WinUsb.C_SHORT, 1).withName("Index"),
        WinUsb.align(WinUsb.C_SHORT, 1).withName("Length")
    ).withName("_WINUSB_SETUP_PACKET");

WinUsb_ControlTransfer (
https://learn.microsoft.com/en-us/windows/win32/api/winusb/nf-winusb-winusb_controltransfer
):

    public static final FunctionDescriptor DESC = FunctionDescriptor.of(
        WinUsb.C_INT,
        WinUsb.C_POINTER,
        _WINUSB_SETUP_PACKET.layout(),
        WinUsb.C_POINTER,
        WinUsb.C_LONG,
        WinUsb.C_POINTER,
        WinUsb.C_POINTER
    );

Regards,
Manuel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/panama-dev/attachments/20250501/51e758c1/attachment.htm>


More information about the panama-dev mailing list