<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Note that if you just want to dispose of the string after the
conversion, you can also do:<br>
<br>
private static String readUtf8String(MemorySegment segment) {<br>
final MemorySegment string =
segment.reinterpret(Long.MAX_VALUE);<br>
String result = string.getUtf8String(0);<br>
NativeMethods.disposeString(segment);<br>
return result;<br>
}</p>
<p>This behaves more or less equivalently to your version. There's
no need to create a new Arena. MemorySegment::reinterpret doesn't
copy the underlying data, but MemorySegment::getUtf8String does.<br>
</p>
<p>Jorn<br>
</p>
<div class="moz-cite-prefix">On 30/09/2023 05:18, tison wrote:<br>
</div>
<blockquote type="cite" cite="mid:CALL9TYJkRzOCtwYk6O=euU_8NTNPwMbniebWO=5L-xZyQ_Q+uA@mail.gmail.com">
<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" moz-do-not-send="true" class="moz-txt-link-freetext">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" moz-do-not-send="true" class="moz-txt-link-freetext">https://docs.oracle.com/en/java/javase/21/docs/specs/jni/functions.html#throw</a><br>
</div>
<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>
</blockquote>
</body>
</html>