<div dir="ltr"><div dir="ltr"><div>Hi Jorn,</div><div><br></div><div>Thanks for looking into this issues.</div><div><br></div><div>As a general remark. My code is publicly available on GitHub (<a href="https://github.com/manuelbl/JavaDoesUSB">https://github.com/manuelbl/JavaDoesUSB</a>) and I even maintain a list of the jextract issues (<a href="https://github.com/manuelbl/JavaDoesUSB/tree/main/java-does-usb/jextract">https://github.com/manuelbl/JavaDoesUSB/tree/main/java-does-usb/jextract</a>).</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Sep 5, 2022 at 3:33 PM Jorn Vernee <<a href="mailto:jorn.vernee@oracle.com">jorn.vernee@oracle.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<p>Hello,</p>
<blockquote type="cite">
<div dir="ltr">
<div>The main thing is: It's not possible to directly process a
header file like winusb.h. Instead, a helper header file needs
to be created:</div>
<div><br>
</div>
<div>#include <windows.h></div>
<div>#include <winusb.h></div>
</div>
</blockquote>
<p>You've probably found this already, but a lot of Windows
functions require including Windows.h instead of the header that
defines the function. The header that should be included is listed
in the table of requirements in the documentation of the function,
for instance for CloseHandle [1], it lists "<b>Header</b>
handleapi.h (include Windows.h)". The DLL is also listed there.</p>
<p>I'm surprised that Windows.h is needed for Winusb.h, since e.g.
WinUsb_Initialize [2] only lists Winusb.h</p>
<p>[1]:
<a href="https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle" target="_blank">https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle</a><br>
[2]:
<a href="https://docs.microsoft.com/en-us/windows/win32/api/winusb/nf-winusb-winusb_initialize" target="_blank">https://docs.microsoft.com/en-us/windows/win32/api/winusb/nf-winusb-winusb_initialize</a></p></div></blockquote><div>Yes, I've figured this out and I have created a helper header file that I'm using for jextract (I think I've communicated this before on the mailing list).<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p><br>
</p>
<blockquote type="cite">
<div dir="ltr">
<div>(1) The generated class _USB_NODE_CONNECTION_INFORMATION_EX
cannot be instanciated. The constructor throws the exception:
java.lang.UnsupportedOperationException: Invalid alignment
requirements for layout s16(DeviceAddress)</div>
<div><br>
</div>
<div>This struct (like many USB descriptors) is packed with
16-bit integer values on odd offsets. jextract insists on
creating a layout with strict alignment rules. So the
generated layout
net.codecrete.usb.windows.gen.usbioctl._USB_NODE_CONNECTION_INFORMATION_EX#$struct$LAYOUT
fails, while the manually created layout
net.codecrete.usb.windows.USBIOCtl#USB_NODE_CONNECTION_INFORMATION_EX$Struct
works.</div>
</div>
</blockquote>
<p>This seems like a bug in jextract.</p>
<p>As a possible workaround, you could generate source code with
`--source` and then manually drop the alignment from the layouts
as well (using .withBitAlignment(8)).<br></p></div></blockquote><div>My current workaround is to use my on struct definition as I often regenerate the source to add more functions and structs.<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p>
</p>
<blockquote type="cite">
<div dir="ltr">
<div>(2) The struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W isn't
usable. In C, it looks like this:</div>
<div><br>
</div>
<div>typedef struct _SP_DEVICE_INTERFACE_DETAIL_DATA_W {<br>
DWORD cbSize;<br>
WCHAR DevicePath[ANYSIZE_ARRAY];<br>
} SP_DEVICE_INTERFACE_DETAIL_DATA_W,
*PSP_DEVICE_INTERFACE_DETAIL_DATA_W;<br>
</div>
<div><br>
</div>
<div dir="ltr">It's basically a variable length struct.
ANYSIZE_ARRAY is defined as 1. But you are supposed to
allocate additional memory for the DevicePath. I guess this is
old style trickery that cannot be solved with an automated
tool.<br>
</div>
</div>
</blockquote>
<p>Yes, I'm not sure there is much we could do automatically.
Especially since this array is not defined without a size, which
would make it a proper incomplete array type.</p>
<p>To work with such arrays, I think the best approach would be to
create an unchecked memory segment starting at the offset of the
array to access the data (using MemorySegment::ofAddress).<br></p></div></blockquote><div>I'm not sure I understand the approach. But I've figured out a workaround. See <a href="https://github.com/manuelbl/JavaDoesUSB/blob/main/java-does-usb/src/main/java/net/codecrete/usb/windows/DeviceProperty.java#L107">https://github.com/manuelbl/JavaDoesUSB/blob/main/java-does-usb/src/main/java/net/codecrete/usb/windows/DeviceProperty.java#L107</a></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p>
</p>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">
<div>Minor annoyances are:</div>
<div><br>
</div>
<div>- jextract on Windows is a batch file that never returns.
So it's not possible to call jextract multiple times for a
single batch file.</div>
</div>
</div>
</blockquote>
I don't see that issue when I run it on my machine. You mean e.g.
`jextract --help` never returns to the command prompt?<br></div></blockquote><div><br></div><div>The problem is different. If I have a batch file like this:</div><div><br></div><div>jextract header1.h</div><div>jextract header2.h</div><div><br></div><div>Then the second command is never executed since jextract never returns to the calling batch file. If you have nested batch file, you would generally need to use "call". But that doesn't help since the command.exe process is replaced with the java process.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
<blockquote type="cite">
<div dir="ltr">
<div dir="ltr">
<div>- It would be nicer if structs used the nice typedef name
instead of the ugly struct name, e.g.
SP_DEVICE_INTERFACE_DATA_W instead of
_SP_DEVICE_INTERFACE_DATA_W (note the leading underscore).</div>
</div>
</div>
</blockquote>
<p>If there is a typedef, jextract should also generate a class with
the nice name which extends the ugly name. It should be possible
to use the class with the nice name instead as well (through
static method "inheritance").</p></div></blockquote><div><br></div><div>This is partially correct. I've figured out that if I include both the struct _SP_DEVICE_INTERFACE_DATA_W and the typedef
SP_DEVICE_INTERFACE_DATA_W, then I can use the nice name
SP_DEVICE_INTERFACE_DATA_W. But if I only include the typedef, it generates any empty class that doesn't inherit from anything (except Object). That looks like a bug to me.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>
<p>Cheers,<br>
Jorn<br>
</p>
<blockquote type="cite"><br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Tue, Aug 23, 2022 at 5:48
AM Sundararajan Athijegannathan <<a href="mailto:sundararajan.athijegannathan@oracle.com" target="_blank">sundararajan.athijegannathan@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div>
<div dir="ltr">
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">Thanks
for your experiments and comments. I'll go over and file
bug(s) as needed.</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><br>
</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">-Sundar</div>
<hr style="display:inline-block;width:98%">
<div id="gmail-m_8438801734776763929gmail-m_-9093422919805539973divRplyFwdMsg" dir="ltr"><font style="font-size:11pt" face="Calibri,
sans-serif" color="#000000"><b>From:</b> jextract-dev
<<a href="mailto:jextract-dev-retn@openjdk.org" target="_blank">jextract-dev-retn@openjdk.org</a>>
on behalf of Manuel Bleichenbacher <<a href="mailto:manuel.bleichenbacher@gmail.com" target="_blank">manuel.bleichenbacher@gmail.com</a>><br>
<b>Sent:</b> 23 August 2022 02:24<br>
<b>To:</b> <a href="mailto:jextract-dev@openjdk.org" target="_blank">jextract-dev@openjdk.org</a>
<<a href="mailto:jextract-dev@openjdk.org" target="_blank">jextract-dev@openjdk.org</a>><br>
<b>Subject:</b> jextract for operating system API</font>
<div> </div>
</div>
<div>
<div dir="ltr">Hi everybody
<div><br>
</div>
<div>As promised, I've compiled my findings when using
jextract for the Java Does USB project, which uses
the foreign function & memory API to communicate
with USB devices on Windows, macOS and Linux. After
initial difficulties with jextract, I've written all
the layouts, method and variable handles manually.
But now I've given jextract another try. The
commands I've used can be found in in the "jextract"
branch of the project at <a href="https://github.com/manuelbl/JavaDoesUSB/tree/jextract/java-does-usb/jextract" target="_blank">https://github.com/manuelbl/JavaDoesUSB/tree/jextract/java-does-usb/jextract</a></div>
<div><br>
</div>
<div>Please note that I think that automatically
generating code for some of the old Windows and
POSIX APIs is almost impossible. My use of jextract
(for OS APIs) is probably far from the main use with
third-party libraries. And I might also have made
mistakes, or there might be a simple solution to my
issues. See my conclusions below for areas where I
think jextract has still potential.</div>
<div><br>
</div>
<div><br>
</div>
<div>Linux:</div>
<div><br>
</div>
<div>Overall, I was able to generate most of what I
needed with jextract. The issues were:</div>
<div><br>
</div>
<div>- Generating code for libsystemd (sd-device.h)
failed with "unknown type name 'intmax_t'". I think
this should be defined by inttypes.h, which is
included. My guess is that clang headers and Linux
headers are mixed up. </div>
<div>- When generating code for usbdevice_fs.h, it
didn't generate the constants for
USBDEVFS_CLAIMINTERFACE and similar ones. The reason
might be that the defines look like functions even
though they evaluate to a constant value.</div>
<div><br>
</div>
<div><br>
</div>
<div>macOS:</div>
<div><br>
</div>
<div>Major parts of macOS are provided in the form of
frameworks and they are treated in a special way,
both when it comes to the header files and dynamic
libraries. As an example, my library uses several
functions from the CoreFoundation framework. In
C/CC++, you can simply include them like so:<br>
<br>
#include <CoreFoundation/CoreFoundation.h><br>
<br>
That's surprising as the file actually resides in
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers/CoreFoundation.h.<br>
<br>
Note that it is in a directory called "Headers" and
not in "CoreFoundation" as the include statement
suggests. The relative path
"CoreFoundation/CoreFoundation.h" does not exist at
all.<br>
<br>
This wouldn't be a big problem if this was just the
entry point. But this pattern is used recursively.
CoreFoundation.h includes about 30 other header
files like this, all with a relative path that does
not exist.<br>
<br>
Xcode magically resolves this. But jextract seems to
be missing this magic. So it cannot be used for any
macOS frameworks. In other words, it cannot be for
the major part of the macOS APIs. My library uses a
single non-framework functions. So using jextract
for macOS is pointless without resolving this issue.<br>
<br>
</div>
<div><br>
</div>
<div>Windows:</div>
<div><br>
</div>
<div>On Windows I spent the most time -- with no
success at all. I only partially understand the
problems. Here is what I've encountered:</div>
<div><br>
</div>
<div>The first simple goal was to have code for
CloseHandle() generated. I tried it three different
ways:</div>
<div>
<ul>
<li>Generating code for handleapi.h generated 1000
classes. Code for CloseHandle() was generated in
2 classes, but none of them was publicly
available.</li>
<li>Generating code for handleapi.h restricted to
the function CloseHandle() generated a small
number of class with a public static method for
CloseHandle(). However, at run-time the method
produces the error
"java.lang.UnsatisfiedLinkError: unresolved
symbol: CloseHandle"</li>
<li>Generating code for windows.h restricted to
CloseHandle() also resulted in
the UnsatisfiedLinkError.</li>
</ul>
<div>I then tried to generate code for Winusb.h.
Unfortunately, this header file is not
independent. It expects that you have already
processed other header files before it. So it
fails with "error: unknown type name
'LARGE_INTEGER'". This behavior with be reproduced
in Visual Studio.</div>
</div>
<div><br>
</div>
<div>Next up was Cfgmgr32.h. It also doesn't seem to
be independent and fails with "error: unknown type
name 'ULONG'". Setupapi.h and Usbioctl.h behave
similarly.</div>
<div><br>
</div>
<div>Windows was the only system where I had problems
with preprocessor macros. The macro _M_AMD64=100 is
certainly needed. That got me further than without
it. And I've defined two Unicode macros, copied from
the Visual Studio project. But the macros might
still be the source of some problems.</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
<div>Conclusion:</div>
<div><br>
</div>
<div>At the moment, jextract doesn't help much for
accessing OS APIs.</div>
<div><br>
</div>
<div>On Linux, the "unknown type name 'intmax_t'" is
worth investigating. It could be helpful for many
APIs.</div>
<div><br>
</div>
<div>On macOS, it's all about the frameworks and the
magic behind resolving the include path. If it can
be made to work, it hopefully opens up the world of
framework (plus some challenges that are still
hidden).</div>
<div><br>
</div>
<div>On Windows, more investigation is needed. Work on
the required macros is needed, as well as more
experiments with header files just built for code
generation (to get beyond the problem of header
files that are not independent).</div>
<div><br>
</div>
<div><br>
</div>
<div>Regards</div>
<div>Manuel</div>
<div> </div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</blockquote>
</div>
</blockquote></div></div>