1

Is it possible to call a function pointer from Java?

To call a C function from Java I can just use the down call method from the CLinker, but that works only for functions and not for function pointers, since it needs a NativeSymbol for the function.

So how can I get a NativeSymbol from a MemoryAddress? Or is there an other possibility to call a function pointer from java code.

My current workaround is to just use C wrapper functions, like this:

void call_function(void (*func)(void)) {
    func();
}

and then just call these functions

    CLinker link = CLinker.systemCLinker();
    MethodHandle handle = link.downcallHandle(link.lookup("get_function_pointer").orElseThrow(), FunctionDescriptor.of(ADDRESS);
    MemoryAddress funcPntr = (MemoryAddress) handle.invoke();
    handle = link.downcallHandle(link.lookup("call_function").orElseThrow(), FunctionDescriptor.of(ADDRESS);
    handle.invoke();
  • Does this approach make sense and done your job? if yes, so leave it as is. – S.A.Parkhid Sep 24 '22 at 21:54
  • Which Java version is this? `NativeSymbol` has been removed in the latest version. – Jorn Vernee Sep 24 '22 at 22:03
  • What Java version? A lot has changed in the last 4 Java versions w.r.t project panama. – Johannes Kuhn Sep 24 '22 at 22:38
  • Also see [NativeSymbol.ofAddress](https://docs.oracle.com/en/java/javase/18/docs/api/jdk.incubator.foreign/jdk/incubator/foreign/NativeSymbol.html#ofAddress%28java.lang.String,jdk.incubator.foreign.MemoryAddress,jdk.incubator.foreign.ResourceScope%29) – Johannes Kuhn Sep 24 '22 at 23:05

1 Answers1

1

Like Johannes Kuhn commented: NativeSymbol.ofAddress is exactly what I need.

So the code looks like this:

CLinker link = CLinker.systemCLinker();
MethodHandle handle = link.downcallHandle(link.lookup("get_function_pointer").orElseThrow(), FunctionDescriptor.of(ADDRESS);
MemoryAddress funcPntr = (MemoryAddress) handle.invoke();
try (ResourceScope scope = ResourceScope.newConfinedScope()) {
    NativeSymbol funcSymbol = NativeSymbol.ofAddress("symbol_name", funcPntr, scope);
    MethodHandle handle = linker.downcallHandle(funcPntr, FunctionDescriptor.ofVoid());
    handle.invoke();
}
  • If you need to call different function pointers, you can create a downcall handle without the NativeSymbol and pass one on each invocation. – Johannes Kuhn Sep 25 '22 at 15:28