On 18/11/2023 06:46, Kasper Nielsen wrote:
Hi Rob,

Delegating caller sensitive methods can be tricky.

Besides the obvious solutions with StackWalker and/or Lookup objects I've
sometimes used an abstract class that must be extended by users of my library.
This may be more trouble in your case than the other solutions though.

In your situation it would be something like this.

// Defined in your library and extendable by users of your library
public abstract class NativeLoader {

     protected abstract MethodHandle downcallHandle(Linker linker, MemorySegment
          address, FunctionDescriptor function, Linker.Option... options);

     public final <T> T load(Class<T> interFace) {
      .. do stuff.
      call this.downcallHandle
      .. do more stuff
     }
}

// Usage by other library
class UsageByOtherLibrary {
    private static final NativeLoader NL = new NativeLoader() {
         protected MethodHandle downcallHandle(Linker linker, MemorySegment
                    address, FunctionDescriptor function, Option... options) {
             return linker.downcallHandle(address, function, options);
         }
     };

     public void main() {
         SomeInterface si = NL.load(SomeInterface.class);
     }
}

The actual call to Linker.downcallHandle is now only performed by the user of
your library. So depending on what you do, you might even be able to avoid
requiring enabling native access for your library. Only the libraries that use
your library would need it.

/Kasper

Hi Kasper,

This would indeed be relatively easiy if Linker.downcallHandle was the only native call, but I've already used AddressLayout.withTargetLayout, and just had to add a call to MemorySegment.reinterpret for the MemorySegment an AddressLayout was referring to (the result of a native call like malloc). Such custom implementations would need to be passed around several method calls of my module. Still, this is something to consider, as it does take away restricted calls away from my module to the caller. Thanks for the hint!

Rob






On Thu, 16 Nov 2023 at 19:21, Rob Spoor <open...@icemanx.nl> wrote:

On 16/11/2023 18:15, Maurizio Cimadamore wrote:

On 16/11/2023 16:54, Rob Spoor wrote:
Hi Maurizio,

I don't think you understand what my module is doing. For instance,
it's not specifying the downcall method handles themselves, it's just
making it easy to define them. Maybe a small example would show what
I'm doing.

Consider the following partial interface from JNA:

     public interface Kernel32 extends StdCallLibrary, WinNT, Wincon {

         /** The instance. */
         Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class,
W32APIOptions.DEFAULT_OPTIONS);

         int GetLastError();
     }

What JNA is doing is creating an implementation based on this
interface that delegates to the native kernel32 library. This is all
done through the Native.load method.

Reply via email to