<div dir="ltr">When I reported the issue related to GetLastError(), I was working on a library for communicating with USB devices from Java. The library has made good progress and the current result is available on GitHub: <a href="https://github.com/manuelbl/JavaDoesUSB">https://github.com/manuelbl/JavaDoesUSB</a>. It runs on Windows, macOS and Linux, both on Intel and ARM processors (I haven't tested ARM on Windows yet) and does not require any additional libraries to be installed.<div><br></div><div>The main use case for project Panama seems to be to make third-party libraries accessible to Java. This library is different: it makes native operating system APIs accessible.</div><div><br></div><div>My experience with project Panama so far:</div><div><br></div><div>Except for the GetLastError() issue, it just works. The VM never crashed because of a bug. And in most cases where I made a mistake with native data structures or function calls, it was caught with a run-time exception. In a few cases, I managed to pass invalid data to API calls, which then crashed the VM.<br><br></div><div>The USB APIs on Windows, macOS and Linux are fundamentally different. So there was hardly any synergies between them. But the code for the Intel and ARM variants on each platform is identical. I guess these two 64-bit architectures have similar concepts for passing arguments and aligning data. But project Panama also seems to take care of some of the differences.</div><div><br></div><div>I've written all the code for the native function calls and native data structures manually. I've tested jextract but found it frustrating (difficult to build, mixup of system headers, excessive number of files and code, strange class and filenames, missing constants/defines etc.). It might work better for a well-written third-party library. But for all the crust that has accumulated in a 40 year old operating system, manual work turned out to be a better option.</div><div><br></div><div>The documentation is clearly insufficient. I had to learn from hitting exception, guessing the causes and experimenting with solutions. And with Google you find a lot of outdated documents. The documentation doesn't seem to explain how members in a StructLayout are aligned, why you can't pass a memory segment created with MemorySegment.ofArray() to a native function etc. And if it does, it is so distributed that I didn't find it.</div><div><br></div><div>Translating C code into Java, I would have expected that this C structure, which requires 4 bytes of padding between timeout and data:</div><div><div><pre style="background-color:rgb(43,43,43);color:rgb(169,183,198);font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(128,128,128)">struct usbdevfs_ctrltransfer {<br></span><span style="color:rgb(128,128,128)">    __u8 bRequestType;<br></span><span style="color:rgb(128,128,128)">    __u8 bRequest;<br></span><span style="color:rgb(128,128,128)">    __u16 wValue;<br></span><span style="color:rgb(128,128,128)">    __u16 wIndex;<br></span><span style="color:rgb(128,128,128)">    __u16 wLength;<br></span><span style="color:rgb(128,128,128)">    __u32 timeout;  /* in milliseconds */<br></span><span style="color:rgb(128,128,128)">    void *data;<br></span><span style="color:rgb(128,128,128)">};<br></span></pre></div><div>simply translates to:</div><div><pre style="background-color:rgb(43,43,43);color:rgb(169,183,198);font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(204,120,50)">public static final </span>GroupLayout <span style="color:rgb(152,118,170);font-style:italic">ctrltransfer$Struct </span>= <span style="font-style:italic">structLayout</span>(<br>        <span style="color:rgb(152,118,170);font-style:italic">JAVA_BYTE</span>.withName(<span style="color:rgb(106,135,89)">"bRequestType"</span>)<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">JAVA_BYTE</span>.withName(<span style="color:rgb(106,135,89)">"bRequest"</span>)<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">JAVA_SHORT</span>.withName(<span style="color:rgb(106,135,89)">"wValue"</span>)<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">JAVA_SHORT</span>.withName(<span style="color:rgb(106,135,89)">"wIndex"</span>)<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">JAVA_SHORT</span>.withName(<span style="color:rgb(106,135,89)">"wLength"</span>)<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">JAVA_INT</span>.withName(<span style="color:rgb(106,135,89)">"timeout"</span>)<span style="color:rgb(204,120,50)">,<br></span><span style="color:rgb(204,120,50)">        </span><span style="color:rgb(152,118,170);font-style:italic">ADDRESS</span>.withName(<span style="color:rgb(106,135,89)">"data"</span>)<br>)<span style="color:rgb(204,120,50)">;<br></span></pre></div><div>After all, ADDRESS has an alignment of 64 bits / 8 bytes. So the padding could be added automatically. But it just throws an error when used. Instead the padding must be specified manually. Very surprising. And even if it needs to be specified manually, I'd rather specify that 'data' needs an 8 byte alignment instead of calculating the padding and adding paddingLayout(32).</div><div><br></div><div>A single time, I hit an implementation limitation: The macOS function CFUUIDGetConstantUUIDWithBytes cannot be implemented (<a href="https://developer.apple.com/documentation/corefoundation/1542189-cfuuidgetconstantuuidwithbytes">https://developer.apple.com/documentation/corefoundation/1542189-cfuuidgetconstantuuidwithbytes</a>). I found a workaround.</div><div><br></div><div>Overall, I like project Panama and hope that it will leave preview phase soon (including a fix for the GetLastError() issue).</div></div><div><br></div><div>My USB library has still a way to go. The next step will be technically challenging: notification about USD devices being plugged in or removed. It will require a run loop and Mach ports on macOS, message handling with message-only windows on Windows and non-blocking I/O with select() on Linux.</div><div><br></div><div>Regards</div><div>Manuel</div><div><br></div></div>