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