Function pointers and GraalVM
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Sep 10 15:49:57 UTC 2025
On 10/09/2025 14:12, Manuel Bleichenbacher wrote:
> Hi Maurizio
>
> The pull request solves something different. It simplifies invoking
> function pointers that are part of a struct. For COM interfaces and
> similar constructs, this is quite useful.
>
> However, the code for the upcall and downcall handle hasn't changed.
> They are still static fields of an inner class. So they will always be
> instantiated as a pair.
>
> But it might be useful to go one step further with this pull request
> and not emit the upcall (method handle, function interface, "apply"
> method) if the "functional" option is specified.
Apologies -- that is what I assumed the changes in the PR did. I believe
it should be possible to at least enhance the PR that way and then try
things out. @Nizar could you please look into this?
I did something like this in our jextract/ONNX/Babylon experiment
https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/src/main/java/oracle/code/onnx/foreign/OrtApi.java
(as you can see there's no upcall handles there, as they were not needed).
> Or even consider emitting code like my Windows API Generator does for
> COM interfaces (see
> https://github.com/manuelbl/WindowsApiGenerator/blob/main/docs/com_interfaces.md
> <https://urldefense.com/v3/__https://github.com/manuelbl/WindowsApiGenerator/blob/main/docs/com_interfaces.md__;!!ACWV5N9M2RV99hQ!IvvUYfukc401IJY8ml05l3Br5O2zP9NNaFN0JHeYgLetR8-G3vGu2SasWYB1phslKRoYTjaelHHiU5OcLIcPmfi7f8dQsqzrow$>).
> It doesn't create an interface for each function pointer, but a single
> one for the entire struct, separate implementation classes for
> downcalls (calling a COM interface) and upcalls (implementing COM
> interfaces).
I _think_ I did something like this in our jextract/ONNX/Babylon experiment
https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/src/main/java/oracle/code/onnx/foreign/OrtApi.java
(as you can see there's no interfaces and no upcall handles there, as
they were not needed).
Is that similar to what you had in mind?
Maurizio
>
> By the way: the current pull request has a further problem. I
> generates code that doesn't compile. Depending on the arguments of the
> function pointer, the setter and the invoker method have the same
> arguments and clash.
>
> Regards
> Manuel
>
>
> Am Mi., 10. Sept. 2025 um 14:25 Uhr schrieb Maurizio Cimadamore
> <maurizio.cimadamore at oracle.com>:
>
> Seems related to this?
>
> https://git.openjdk.org/jextract/pull/287
>
> It would be very helpful if you could try the option in that PR
> (you would need to build jextract manually) and see if that
> improves the situation.
>
> Cheers
> Maurizio
>
> On 10/09/2025 12:46, Manuel Bleichenbacher wrote:
>> Hi jextract team
>>
>> I've been playing with the upcoming GraalVM 25 and its support
>> for FFM. But I've run into an issue with code generated by
>> jextract related to function pointers: it always instantiates
>> both the downcall and upcall method handles, independent of which
>> one is actually used. In my case, I would only need the downcall
>> handle. The unnecessary upcall handle depends on another method
>> ("apply") that GraalVM has correctly identified to never be
>> called and is thus omitted from the native image. As a result,
>> the application crashes at run-time.
>>
>> It wouldn't be such a problem if I was dealing with one or two
>> function pointers. Then I would manually create the required FFM
>> code with downcall handles only. However, I'm dealing with COM
>> interfaces and the macOS IOKit version thereof:
>>
>> *typedef**struct*IOUSBInterfaceStruct942{
>>
>> IUNKNOWN_C_GUTS;
>>
>> IOReturn (*CreateInterfaceAsyncEventSource)(*void* **self*,
>> CFRunLoopSourceRef *source);
>>
>> CFRunLoopSourceRef (*GetInterfaceAsyncEventSource)(*void* **self*);
>>
>> IOReturn (*CreateInterfaceAsyncPort)(*void* **self*, mach_port_t
>> *port);
>>
>> mach_port_t (*GetInterfaceAsyncPort)(*void* **self*);
>>
>> IOReturn (*USBInterfaceOpen)(*void* **self*);
>>
>> IOReturn (*USBInterfaceClose)(*void* **self*);
>>
>> IOReturn (*GetInterfaceClass)(*void* **self*, UInt8 *intfClass);
>>
>> IOReturn (*GetInterfaceSubClass)(*void* **self*, UInt8
>> *intfSubClass);
>>
>> IOReturn (*GetInterfaceProtocol)(*void* **self*, UInt8
>> *intfProtocol);
>>
>> IOReturn (*GetDeviceVendor)(*void* **self*, UInt16 *devVendor);
>>
>> ...
>>
>>
>> These are structs that almost exclusively consist of function
>> pointers. In the case of IOKit, the two main ones consist of 40
>> and 50 function pointers.
>>
>> Am I correct that there is currently no way to suppress the
>> generation of upcall method handles?
>>
>> Are there any plans to to make the jextract generated code work
>> well with GraalVM?
>>
>> Regards
>> Manuel
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/jextract-dev/attachments/20250910/80415163/attachment-0001.htm>
More information about the jextract-dev
mailing list