JDK-18 Внешние функции: как вызывать нестатические функции?
Я играл с
Одна вещь, которую я не могу понять: как использовать нестатическую функцию JVM?
Если я не могу, как мне передать некоторый контекст вниз и назад, чтобы я мог привести контекст к правильному экземпляру/типу в статической функции java? Как в java создать
Единственный способ, которым я могу понять, как это сделать, - сохранить список созданных классов и выполнить круговой обход индекса в списке. Что похоже на взлом.
Может быть, JVM оставляет за собой право перемещать память JVM без ограничений, когда захочет, так что, может быть, это невозможно? Если да, то какой рекомендуемый шаблон для этого?
--- редактировать - Добавить пример кода ---
public class RoundTripExample {
private String name;
RoundTripExample(String _name) {
this.name = _name;
}
public void callback() {
System.out.println("Called from native"+name);
}
public static void main(String[] args) throws Throwable {
var fName = new File("../zig/zig-out/lib/libnativeFuncs.so").getCanonicalFile();
System.load(fName.toString());
var instance =new RoundTripExample("round trip name");
CLinker link = CLinker.systemCLinker();
SymbolLookup symLook = SymbolLookup.loaderLookup();
ResourceScope scope = ResourceScope.newSharedScope();
var nativeFunc = link.downcallHandle(
symLook.lookup("zigCallTest").get(),
FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.ADDRESS)
);
var handle =
MethodHandles.lookup().findVirtual(
RoundTripExample.class,
"callback",
MethodType.methodType(void.class)
);
handle.bindTo(instance);
var upcall = link.upcallStub(
handle,
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS),
ZigStubs.scope
);
nativeFunc.invoke(upcall);
}
}
Предполагая, что это способ сделать это, проблема заключается в создании
1 ответ
Если контекст, который вам нужно передать, является постоянным для целевой функции, вы можете привязать его к дескриптору целевого метода, используяMethodHandles.insertArguments
а затем используйте полученный дескриптор метода для создания заглушки восходящего вызова.
Если контекст не является постоянным для целевой функции, то ваша идея использования списка и передачи индекса объекту, который вы хотите, является довольно хорошим способом. По сути, это способ превратить объект в целое число, вставив его в список, а затем обратно в объект, снова найдя его в списке.
Нет безопасного способа превратить объект в простой собственный адрес, поскольку, как вы говорите, объект может быть перемещен JVM.
В примере использование выглядит осуществимым. В этом случае вы забыли присвоить результат
bindTo
:
handle = handle.bindTo(instance);
Кроме того, вам придется отказаться от аргумента адреса, переданного из собственного кода, поскольку похоже, что он не используется вашим кодом Java:
handle = MethodHandles.dropArguments(handle, 0, MemoryAddress.class);
var upcall = link.upcallStub(
handle,
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS),
ZigStubs.scope
);