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