<div dir="ltr">Hi Maurizio<div><br></div><div>Yes, your experiment code is exactly what would be needed. It has the simple static invoker method (as proposed by the pull requests) and it does not generate code for getter, setter and upcalls. It's probably all that is needed for the "functional struct" use case.</div><div><br></div><div>Regards</div><div>Manuel</div><div><br></div></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">Am Mi., 10. Sept. 2025 um 17:50 Uhr schrieb Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com">maurizio.cimadamore@oracle.com</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><u></u>

  
  <div>
    <p><br>
    </p>
    <div>On 10/09/2025 14:12, Manuel
      Bleichenbacher wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">Hi Maurizio
        <div><br>
        </div>
        <div>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.</div>
        <div><br>
        </div>
        <div>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.</div>
        <div><br>
        </div>
        <div>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. </div>
      </div>
    </blockquote>
    <p>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?</p>
    <p>I did something like this in our jextract/ONNX/Babylon experiment</p>
    <p><a href="https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/src/main/java/oracle/code/onnx/foreign/OrtApi.java" target="_blank">https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/src/main/java/oracle/code/onnx/foreign/OrtApi.java</a></p>
    <p>(as you can see there's no upcall handles there, as they were not
      needed).<br>
    </p>
    <blockquote type="cite">
      <div dir="ltr">
        <div>Or even consider emitting code like my Windows API
          Generator does for COM interfaces (see <a href="https://urldefense.com/v3/__https://github.com/manuelbl/WindowsApiGenerator/blob/main/docs/com_interfaces.md__;!!ACWV5N9M2RV99hQ!IvvUYfukc401IJY8ml05l3Br5O2zP9NNaFN0JHeYgLetR8-G3vGu2SasWYB1phslKRoYTjaelHHiU5OcLIcPmfi7f8dQsqzrow$" target="_blank">https://github.com/manuelbl/WindowsApiGenerator/blob/main/docs/com_interfaces.md</a>).
          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).</div>
      </div>
    </blockquote>
    <p>I _think_ I did something like this in our jextract/ONNX/Babylon
      experiment</p>
    <p><a href="https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/src/main/java/oracle/code/onnx/foreign/OrtApi.java" target="_blank">https://github.com/openjdk/babylon/blob/code-reflection/cr-examples/onnx/src/main/java/oracle/code/onnx/foreign/OrtApi.java</a></p>
    <p>(as you can see there's no interfaces and no upcall handles
      there, as they were not needed).<br>
    </p>
    <p></p>
    <p>Is that similar to what you had in mind?</p>
    <p>Maurizio<br>
    </p>
    <blockquote type="cite">
      <div dir="ltr">
        <div><br>
        </div>
        <div>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.</div>
        <div><br>
        </div>
        <div>Regards</div>
        <div>Manuel</div>
        <div><br>
        </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr" class="gmail_attr">Am Mi., 10. Sept. 2025 um
          14:25 Uhr schrieb Maurizio Cimadamore <<a href="mailto:maurizio.cimadamore@oracle.com" target="_blank">maurizio.cimadamore@oracle.com</a>>:<br>
        </div>
        <blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
          <div>
            <p>Seems related to this?</p>
            <p><a href="https://git.openjdk.org/jextract/pull/287" target="_blank">https://git.openjdk.org/jextract/pull/287</a></p>
            <p>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.</p>
            <p>Cheers<br>
              Maurizio<br>
            </p>
            <div>On 10/09/2025 12:46, Manuel Bleichenbacher wrote:<br>
            </div>
            <blockquote type="cite">
              <div dir="ltr">Hi jextract team
                <div><br>
                </div>
                <div>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.</div>
                <div><br>
                </div>
                <div>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:</div>
                <div><br>
                </div>
                <div>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgb(11,79,121)"><span style="color:rgb(155,35,147)"><b>typedef</b></span><span style="color:rgba(0,0,0,0.85)"> </span><span style="color:rgb(155,35,147)"><b>struct</b></span><span style="color:rgba(0,0,0,0.85)"> </span>IOUSBInterfaceStruct942<span style="color:rgba(0,0,0,0.85)"> {</span></p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgb(15,104,160)"><span style="color:rgba(0,0,0,0.85)"><span>    </span></span>IUNKNOWN_C_GUTS<span style="color:rgba(0,0,0,0.85)">;</span></p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*CreateInterfaceAsyncEventSource)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>,
                    <span style="color:rgb(57,0,160)">CFRunLoopSourceRef</span>
                    *source);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">CFRunLoopSourceRef</span>
                    (*GetInterfaceAsyncEventSource)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*CreateInterfaceAsyncPort)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>,
                    <span style="color:rgb(57,0,160)">mach_port_t</span>
                    *port);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">mach_port_t</span>
                    (*GetInterfaceAsyncPort)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*USBInterfaceOpen)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*USBInterfaceClose)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*GetInterfaceClass)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>,
                    <span style="color:rgb(57,0,160)">UInt8</span>
                    *intfClass);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*GetInterfaceSubClass)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>,
                    <span style="color:rgb(57,0,160)">UInt8</span>
                    *intfSubClass);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*GetInterfaceProtocol)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>,
                    <span style="color:rgb(57,0,160)">UInt8</span>
                    *intfProtocol);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"><span> 
                        </span><span style="color:rgb(57,0,160)">IOReturn</span>
                    (*GetDeviceVendor)(<span style="color:rgb(155,35,147)"><b>void</b></span> *<span style="color:rgb(155,35,147)"><b>self</b></span>,
                    <span style="color:rgb(57,0,160)">UInt16</span>
                    *devVendor);</p>
                  <p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;font-size-adjust:none;font-kerning:auto;font-variant-alternates:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-east-asian:normal;font-feature-settings:normal;color:rgba(0,0,0,0.85)"> 
                      ...</p>
                  <br>
                </div>
                <div>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.</div>
                <div><br>
                </div>
                <div>Am I correct that there is currently no way to
                  suppress the generation of upcall method handles?</div>
                <div><br>
                </div>
                <div>Are there any plans to to make the jextract
                  generated code work well with GraalVM?</div>
                <div><br>
                </div>
                <div>Regards</div>
                <div>Manuel</div>
                <div><br>
                </div>
              </div>
            </blockquote>
          </div>
        </blockquote>
      </div>
    </blockquote>
  </div>

</blockquote></div>