<div dir="ltr"><div class="gmail_default" style="font-family:arial,sans-serif">Thank you! Finally I work out a string conversion utility:</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">    private static String readUtf8String(MemorySegment segment) {<br>        try (Arena arena = Arena.ofConfined()) {<br>            final MemorySegment string = segment.reinterpret(Long.MAX_VALUE, arena, NativeMethods::disposeString);<br>            return string.getUtf8String(0);<br>        }<br>    }<br></div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">#[no_mangle]<br>pub unsafe extern "C" fn dispose_string(s: *mut c_char) {<br>    drop(CString::from_raw(s))<br>}<br></div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">Hopefully, this doesn't create too much overhead (I'm not sure the overhead of creating Arena), and no other leaks. It likes JNIEnv#NewString and IIUC JNIEnv#NewString also copy bytes.</div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div class="gmail_default" style="font-family:arial,sans-serif">> <span style="font-family:Arial,Helvetica,sans-serif">Native functions can just return NULL/0, and the linker will automatically translate that into MemorySegment.NULL.</span></div><div class="gmail_default" style="font-family:arial,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif"><br></span></div><div class="gmail_default" style="font-family:arial,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif">Good to know!</span></div><div class="gmail_default" style="font-family:arial,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif"><br></span></div><div class="gmail_default" style="font-family:arial,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif">> </span><span style="font-family:Arial,Helvetica,sans-serif">So, there is no FFM-specific API for the native code to interact with the Java side</span></div><div class="gmail_default" style="font-family:arial,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif"><br></span></div><div class="gmail_default" style="font-family:arial,sans-serif"><span style="font-family:Arial,Helvetica,sans-serif">OK. Perhaps I should return an error union in this case and decode & throw exceptions on the Java side.</span></div><div class="gmail_default" style="font-family:arial,sans-serif"><br></div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><font face="arial, sans-serif">Best,</font></div><div><font face="arial, sans-serif">tison.</font></div></div></div></div></div></div></div></div></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Jorn Vernee <<a href="mailto:jorn.vernee@oracle.com">jorn.vernee@oracle.com</a>> 于2023年9月29日周五 23:42写道:<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 class="gmail_default" style="font-family:arial,sans-serif">>
      And, if we think of error handling, how do we properly return a
      NULL from native methods, and how do we throw exceptions from
      native methods?</div>
    <div class="gmail_default" style="font-family:arial,sans-serif">>
      MemorySegment.NULL seems an Object without overriding equals, and
      JNIEnv's throw counterpart is missing or I don't find it (perhaps
      upcall helps but it's still a bit away from real-world usage).</div>
    <div class="gmail_default" style="font-family:arial,sans-serif"><br>
    </div>
    <div class="gmail_default" style="font-family:arial,sans-serif">Native
      functions can just return NULL/0, and the linker will
      automatically translate that into MemorySegment.NULL.</div>
    <div class="gmail_default" style="font-family:arial,sans-serif"><br>
    </div>
    <div class="gmail_default" style="font-family:arial,sans-serif">As
      for throwing a Java exception from native code, similar to what is
      possible with JNI Throw(New) [1], this is not supported. The
      Linker operates on the general assumption that the native code it
      is interacting with has no knowledge about Java at all. So, there
      is no FFM-specific API for the native code to interact with the
      Java side.<br>
    </div>
    <div class="gmail_default" style="font-family:arial,sans-serif"><br>
    </div>
    <div class="gmail_default" style="font-family:arial,sans-serif">Jorn</div>
    <div class="gmail_default" style="font-family:arial,sans-serif"><br>
    </div>
    <div class="gmail_default" style="font-family:arial,sans-serif">[1]:
<a href="https://docs.oracle.com/en/java/javase/21/docs/specs/jni/functions.html#throw" target="_blank">https://docs.oracle.com/en/java/javase/21/docs/specs/jni/functions.html#throw</a><br>
    </div>
    <p></p>
    <div>On 29/09/2023 16:08, tison wrote:<br>
    </div>
    <blockquote type="cite">
      
      <div dir="ltr">
        <div class="gmail_default" style="font-family:arial,sans-serif">Here
          is my native method written in Rust:</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">#[no_mangle]<br>
          pub unsafe extern "C" fn datafusion_version() -> *const
          c_char {<br>
             
          CString::new(datafusion::DATAFUSION_VERSION).unwrap().into_raw()<br>
          }<br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">And
          below is my attempt to bind it with FFM APIs:</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif"> 
            static MethodHandle createMethodHandle(String name,
          FunctionDescriptor descriptor) {<br>
                  final MemorySegment fp =
          LOADER.lookup.find(name).orElseThrow();<br>
                  return LOADER.linker.downcallHandle(fp, descriptor);<br>
              }<br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif"> 
            private static final MethodHandle
          datafusionVersionMethodHandle =
          NativeLoader.createMethodHandle(datafusionVersionMethodName,
          datafusionVersionMethodDesc);<br>
          <br>
              @SneakyThrows<br>
              public static String datafusionVersion() {<br>
                  final MemorySegment version = (MemorySegment)
          datafusionVersionMethodHandle.invokeExact();<br>
                  return version.getUtf8String(0);<br>
              }<br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">I
          noticed that the returned MemorySegment is always with length
          0 and thus any access with return OutOfBoundException.</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">In
          the demos from JEP, all memory segments are allocated from the
          Java side and the native code only move or modify those
          allocated memory segments instead of allocate/shrink memory.</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">I
          wonder what is the formal method to allocate a string from
          native methods and pass back to the Java world.</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">And,
          if we think of error handling, how do we properly return a
          NULL from native methods, and how do we throw exceptions from
          native methods?</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div class="gmail_default" style="font-family:arial,sans-serif">MemorySegment.NULL
          seems an Object without overriding equals, and JNIEnv's throw
          counterpart is missing or I don't find it (perhaps upcall
          helps but it's still a bit away from real-world usage).</div>
        <div class="gmail_default" style="font-family:arial,sans-serif"><br>
        </div>
        <div>
          <div dir="ltr" class="gmail_signature">
            <div dir="ltr">
              <div>
                <div dir="ltr">
                  <div>
                    <div dir="ltr">
                      <div>
                        <div dir="ltr">
                          <div><font face="arial, sans-serif">Best,</font></div>
                          <div><font face="arial, sans-serif">tison.</font></div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </blockquote>
  </div>

</blockquote></div>