Funneling Objects through void*
Johannes Kuhn
info at j-kuhn.de
Thu Jun 15 16:18:59 UTC 2023
Yes, I have read the thread. That StackOverflow question (and the
thread) was just an other trigger to discuss a IMHO a more fundamental
primitive: Passing an java object through a void* pointer.
In the case of EnumWindows, a use of ScopedValue is possible, because
the reference does not "escape" the scope.
In other cases, such as bindings for other languages, the reference may
survive the call and is used at some later point - in which case
ScopedValue does not work.
Of course it is also possible to use some static Map to map from the
pointer to the object.
But those are implementation details.
I just want a pair of methods that turn an object into a pointer and
back - preferably with a deterministic "deallocation".
How that is implemented is a different story.
- Johannes
On 15-Jun-23 18:10, Maurizio Cimadamore wrote:
> There are few options to do this. In Java 20/21 you can use a
> ScopedValue to set up the implicit parameter that needs to be used for
> the callback, if you want a full Java solution.
>
> Or, as discussed here:
>
> https://mail.openjdk.org/pipermail/panama-dev/2023-May/019079.html
>
> It is also possible to wrap some JNI functions in a small library, and
> then call them using FFM. That will allow you to create, destroy and
> access JNI handles.
>
> As discussed in that email, it is possible that at some point in the
> future, FFM/Linker might provide some more direct support for linking to
> JNI (likely, via some helper class).
>
> Cheers
> Maurizio
>
> On 15/06/2023 17:05, Johannes Kuhn wrote:
>> When trying to help this StackOverflow question[1], I tried to use
>> `EnumWindows`[2]. EnumWindows takes a callback and a void* parameter
>> and invokes the callback using the toplevel HWND & the passed void*
>> parameter.
>>
>> Currently I have to create a new upcall stub for every invocation, but
>> if I could funnel some java.lang.Object through the void* parameter, I
>> would only need to create a single upcall, where I retrieve the
>> object, cast it and call some method on it.
>>
>> Example (pseudo) code:
>>
>> public interface EnumWindowsCallback {
>> int callback(long hwnd);
>> }
>> private static int enumWindowsUpcall(long hwnd, MemoryAddress obj) {
>> return (int) ((EnumWindowsCallback)
>> toObject(obj)).callback(hwnd);
>> }
>>
>> public static int enumWindows(EnumWindowsCallback cb) throws
>> Throwable {
>> try (Arena arena = Arena.ofConfined()) {
>> return (int)
>> ENUM_WINDOWS_MH.invokeExact(ENUM_WINDOWS_UPCALL, toPointer(arena, cb));
>> }
>> }
>>
>> One problem is that the arena is not accessible within the callback.
>>
>>
>> Of course it is trivial to write such functionally using a counter and
>> a ConcurrentHashMap, but that is not the only possible implementation.
>>
>> In fact the JNI functions `newGlobalRef` and `deleteGlobalRef` would
>> provide an adequate implementation.
>>
>> - Johannes
>>
>> [1]:
>> https://stackoverflow.com/questions/75620948/how-do-i-get-the-hwnd-of-a-canvas-using-panama/
>> [2]:
>> https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows
More information about the panama-dev
mailing list