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