<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>I like this. The use of record components should probably
preserve the fact that the upcall method handle is treated as a
constant.</p>
<p>This seems related to this PR under review:</p>
<p><a class="moz-txt-link-freetext" href="https://git.openjdk.org/jextract/pull/279">https://git.openjdk.org/jextract/pull/279</a></p>
<p>So we should make sure to decide what code we want to generate
(as that PR will make function pointer support even more verbose).</p>
<p>Cheers<br>
Maurizio<br>
</p>
<div class="moz-cite-prefix">On 07/04/2025 13:42, Duncan Gittins
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CABOqcFs0fbhtVR9-+U5pN6E2Gwo3WyA81q=T=XPFGpp2GaLJJA@mail.gmail.com">
<div dir="ltr">
<div>I've been using jextract successfully for some time now and
it has made it very easy to call into various Windows. Great
work.</div>
<div><br>
</div>
<div>One area which seems a bit verbose is the handling of the
functional interface callbacks for upcalls. For example, the
qsort compare callback is as follows (I've shortened the
jextract version here):</div>
<div><br>
</div>
<div>
<div style="background-color:rgb(255,255,255);padding:0px 0px 0px 2px">
<div style="color:rgb(0,0,0);background-color:rgb(255,255,255);font-family:"Consolas";font-size:10pt;white-space:pre"><p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">class</span><span style="color:rgb(0,0,0)"> QsortCompareFunc {</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> QsortCompareFunc() { }</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/** The function pointer signature, expressed as a functional interface */</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">interface</span><span style="color:rgb(0,0,0)"> Function {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">int</span><span style="color:rgb(0,0,0)"> apply(MemorySegment </span><span style="color:rgb(106,62,62)">_x0</span><span style="color:rgb(0,0,0)">, MemorySegment </span><span style="color:rgb(106,62,62)">_x1</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">private</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">final</span><span style="color:rgb(0,0,0)"> FunctionDescriptor </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">$DESC</span><span style="color:rgb(0,0,0)"> = FunctionDescriptor.</span><span style="color:rgb(0,0,0);font-style:italic">of</span><span style="color:rgb(0,0,0)">(</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> C_h.C_INT,</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> C_h.C_POINTER,</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> C_h.C_POINTER</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> );</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/** The descriptor of this function pointer */</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> FunctionDescriptor descriptor() {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">return</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">$DESC</span><span style="color:rgb(0,0,0)">;</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">private</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">final</span><span style="color:rgb(0,0,0)"> MethodHandle </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">UP$MH</span><span style="color:rgb(0,0,0)"> = C_h.upcallHandle(QsortCompareFunc.Function.</span><span style="color:rgb(127,0,85);font-weight:bold">class</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(42,0,255)">"apply"</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">$DESC</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/**</span></p><p style="margin:0px"><span style="color:rgb(63,95,191)"> * Allocates a new upcall stub, whose implementation is defined by {@code fi}.</span></p><p style="margin:0px"><span style="color:rgb(63,95,191)"> * The lifetime of the returned segment is managed by {@code arena}</span></p><p style="margin:0px"><span style="color:rgb(63,95,191)"> */</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> MemorySegment allocate(QsortCompareFunc.Function </span><span style="color:rgb(106,62,62)">fi</span><span style="color:rgb(0,0,0)">, Arena </span><span style="color:rgb(106,62,62)">arena</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">return</span><span style="color:rgb(0,0,0)"> Linker.</span><span style="color:rgb(0,0,0);font-style:italic">nativeLinker</span><span style="color:rgb(0,0,0)">().upcallStub(</span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">UP$MH</span><span style="color:rgb(0,0,0)">.bindTo(</span><span style="color:rgb(106,62,62)">fi</span><span style="color:rgb(0,0,0)">), </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">$DESC</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">arena</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">private</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">final</span><span style="color:rgb(0,0,0)"> MethodHandle </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">DOWN$MH</span><span style="color:rgb(0,0,0)"> = Linker.</span><span style="color:rgb(0,0,0);font-style:italic">nativeLinker</span><span style="color:rgb(0,0,0)">().downcallHandle(</span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">$DESC</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/**</span></p><p style="margin:0px"><span style="color:rgb(63,95,191)"> * Invoke the upcall stub {@code funcPtr}, with given parameters</span></p><p style="margin:0px"><span style="color:rgb(63,95,191)"> */</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">int</span><span style="color:rgb(0,0,0)"> invoke(MemorySegment </span><span style="color:rgb(106,62,62)">funcPtr</span><span style="color:rgb(0,0,0)">,MemorySegment </span><span style="color:rgb(106,62,62)">_x0</span><span style="color:rgb(0,0,0)">, MemorySegment </span><span style="color:rgb(106,62,62)">_x1</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">try</span><span style="color:rgb(0,0,0)"> {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">return</span><span style="color:rgb(0,0,0)"> (</span><span style="color:rgb(127,0,85);font-weight:bold">int</span><span style="color:rgb(0,0,0)">) </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">DOWN$MH</span><span style="color:rgb(0,0,0)">.invokeExact(</span><span style="color:rgb(106,62,62)">funcPtr</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">_x0</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">_x1</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> } </span><span style="color:rgb(127,0,85);font-weight:bold">catch</span><span style="color:rgb(0,0,0)"> (Throwable </span><span style="color:rgb(106,62,62)">ex$</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">throw</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">new</span><span style="color:rgb(0,0,0)"> AssertionError(</span><span style="color:rgb(42,0,255)">"should not reach here"</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">ex$</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)">}</span></p></div>
</div>
</div>
<div><br>
</div>
<div>I made a few changes in jextract to make the callbacks
generate interface rather than a class, adding a helper record
Upcall to do most of the actions:</div>
<div><br>
</div>
<div>
<div style="background-color:rgb(255,255,255);padding:0px 0px 0px 2px">
<div style="color:rgb(0,0,0);background-color:rgb(255,255,255);font-family:"Consolas";font-size:10pt;white-space:pre"><p style="margin:0px"><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">interface</span><span style="color:rgb(0,0,0)"> QsortCompareFunc {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/** The function pointer signature, expressed as a functional interface */</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">int</span><span style="color:rgb(0,0,0)"> apply(MemorySegment </span><span style="color:rgb(106,62,62)">_x0</span><span style="color:rgb(0,0,0)">, MemorySegment </span><span style="color:rgb(106,62,62)">_x1</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">final</span><span style="color:rgb(0,0,0)"> C_h.Upcall<QsortCompareFunc> </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">UPCALL</span><span style="color:rgb(0,0,0)"> = </span><span style="color:rgb(127,0,85);font-weight:bold">new</span><span style="color:rgb(0,0,0)"> C_h.Upcall<>(QsortCompareFunc.</span><span style="color:rgb(127,0,85);font-weight:bold">class</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(42,0,255)">"apply"</span><span style="color:rgb(0,0,0)">, FunctionDescriptor.</span><span style="color:rgb(0,0,0);font-style:italic">of</span><span style="color:rgb(0,0,0)">(</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> C_h.</span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">C_INT</span><span style="color:rgb(0,0,0)">,</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> C_h.</span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">C_POINTER</span><span style="color:rgb(0,0,0)">,</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> C_h.</span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">C_POINTER</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> ));</span></p><p style="margin:0px">
</p><div style="background-color:rgb(255,255,255);padding:0px 0px 0px 2px"><div style="color:rgb(0,0,0);background-color:rgb(255,255,255);font-family:"Consolas";font-size:10pt;white-space:pre"><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,127,95)">// </span><span style="color:rgb(63,127,95)">A </span><span style="color:rgb(63,127,95)">new upcall stub </span><span style="color:rgb(63,127,95)">is </span><span style="background-color:rgb(255,255,255);padding:0px 0px 0px 2px"><span style="color:rgb(0,0,0);background-color:rgb(255,255,255);font-family:"Consolas";font-size:10pt;white-space:pre"><span style="color:rgb(63,127,95)">allocated </span></span></span><span style="color:rgb(63,127,95)">by</span>:</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,127,95)">// MemorySegment funcPtr = QsortCompareFunc.UPCALL.allocate(fi,arena)</span></p><p style="margin:0px">
</p></div></div><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/**</span></p><p style="margin:0px"><span style="color:rgb(63,95,191)"> * Invoke the upcall stub {@code funcPtr}, with given parameters</span></p><p style="margin:0px"><span style="color:rgb(63,95,191)"> */</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">int</span><span style="color:rgb(0,0,0)"> invoke(MemorySegment </span><span style="color:rgb(106,62,62)">funcPtr</span><span style="color:rgb(0,0,0)">,MemorySegment </span><span style="color:rgb(106,62,62)">_x0</span><span style="color:rgb(0,0,0)">, MemorySegment </span><span style="color:rgb(106,62,62)">_x1</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">try</span><span style="color:rgb(0,0,0)"> {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">return</span><span style="color:rgb(0,0,0)"> (</span><span style="color:rgb(127,0,85);font-weight:bold">int</span><span style="color:rgb(0,0,0)">) </span><span style="color:rgb(0,0,192);font-style:italic;font-weight:bold">UPCALL</span><span style="color:rgb(0,0,0)">.downcall().invokeExact(</span><span style="color:rgb(106,62,62)">funcPtr</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">_x0</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">_x1</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> } </span><span style="color:rgb(127,0,85);font-weight:bold">catch</span><span style="color:rgb(0,0,0)"> (Throwable </span><span style="color:rgb(106,62,62)">ex$</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">throw</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">new</span><span style="color:rgb(0,0,0)"> AssertionError(</span><span style="color:rgb(42,0,255)">"should not reach here"</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">ex$</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)">}</span></p></div>
</div>
<br>
</div>
<div>This reduces the definition somewhat, as long as the top
level header has a record to handle all callback interfaces:</div>
<div><br>
</div>
<div>
<div style="background-color:rgb(255,255,255);padding:0px 0px 0px 2px">
<div style="color:rgb(0,0,0);background-color:rgb(255,255,255);font-family:"Consolas";font-size:10pt;white-space:pre"><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">record</span><span style="color:rgb(0,0,0)"> Upcall<FunctionInterface>(FunctionDescriptor </span><span style="color:rgb(106,62,62)">descriptor</span><span style="color:rgb(0,0,0)">, MethodHandle </span><span style="color:rgb(106,62,62)">upcall</span><span style="color:rgb(0,0,0)">, MethodHandle </span><span style="color:rgb(106,62,62)">downcall</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> Upcall(Class<FunctionInterface> </span><span style="color:rgb(106,62,62)">fi</span><span style="color:rgb(0,0,0)">, String </span><span style="color:rgb(106,62,62)">name</span><span style="color:rgb(0,0,0)">, FunctionDescriptor </span><span style="color:rgb(106,62,62)">descriptor</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">this</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(106,62,62)">descriptor</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(0,0,0);font-style:italic">upcallHandle</span><span style="color:rgb(0,0,0)">(</span><span style="color:rgb(106,62,62)">fi</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">name</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">descriptor</span><span style="color:rgb(0,0,0)">), Linker.</span><span style="color:rgb(0,0,0);font-style:italic">nativeLinker</span><span style="color:rgb(0,0,0)">().downcallHandle(</span><span style="color:rgb(106,62,62)">descriptor</span><span style="color:rgb(0,0,0)">));</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/** Find Java method handle of interface for upcall from native </span><span style="color:rgb(127,127,159)">-></span><span style="color:rgb(63,95,191)"> Java */</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">static</span><span style="color:rgb(0,0,0)"> MethodHandle upcallHandle(Class<?> </span><span style="color:rgb(106,62,62)">fi</span><span style="color:rgb(0,0,0)">, String </span><span style="color:rgb(106,62,62)">name</span><span style="color:rgb(0,0,0)">, FunctionDescriptor </span><span style="color:rgb(106,62,62)">fdesc</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">try</span><span style="color:rgb(0,0,0)"> {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">return</span><span style="color:rgb(0,0,0)"> MethodHandles.</span><span style="color:rgb(0,0,0);font-style:italic">lookup</span><span style="color:rgb(0,0,0)">().findVirtual(</span><span style="color:rgb(106,62,62)">fi</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">name</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">fdesc</span><span style="color:rgb(0,0,0)">.toMethodType());</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> } </span><span style="color:rgb(127,0,85);font-weight:bold">catch</span><span style="color:rgb(0,0,0)"> (ReflectiveOperationException </span><span style="color:rgb(106,62,62)">ex</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">throw</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">new</span><span style="color:rgb(0,0,0)"> AssertionError(</span><span style="color:rgb(106,62,62)">ex</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px">
</p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(63,95,191)">/// Allocate java stub for upcall</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">public</span><span style="color:rgb(0,0,0)"> MemorySegment allocate(FunctionInterface </span><span style="color:rgb(106,62,62)">javaImpl</span><span style="color:rgb(0,0,0)">, Arena </span><span style="color:rgb(106,62,62)">scope</span><span style="color:rgb(0,0,0)">) {</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(127,0,85);font-weight:bold">return</span><span style="color:rgb(0,0,0)"> Linker.</span><span style="color:rgb(0,0,0);font-style:italic">nativeLinker</span><span style="color:rgb(0,0,0)">().upcallStub(</span><span style="color:rgb(0,0,192)">upcall</span><span style="color:rgb(0,0,0)">.bindTo(</span><span style="color:rgb(106,62,62)">javaImpl</span><span style="color:rgb(0,0,0)">), </span><span style="color:rgb(0,0,192)">descriptor</span><span style="color:rgb(0,0,0)">, </span><span style="color:rgb(106,62,62)">scope</span><span style="color:rgb(0,0,0)">);</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px"><span style="color:rgb(0,0,0)"> }</span></p><p style="margin:0px">
</p><p style="margin:0px">Worth considering?</p><p style="margin:0px">
</p><p style="margin:0px">Duncan</p></div>
</div>
<br>
</div>
<div><br>
</div>
<div><br>
</div>
<div><br>
</div>
</div>
</blockquote>
</body>
</html>