Funneling Objects through void*
Johannes Kuhn
info at j-kuhn.de
Thu Jun 15 16:05:42 UTC 2023
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