JNR使用指针参数进行回调/关闭

use*_*ser 5 c java jnr

我正在使用JNR并尝试传递具有以下C等效签名的回调函数:

int fn(void const*, void const**, void**)
Run Code Online (Sandbox Code Playgroud)

进入一些C函数。我已将嵌套在Java方面的JNR库接口中的回调声明为:

public static interface Fn {
  @Delegate public int call(Pointer a, Pointer[] b, Pointer[] c);
}
Run Code Online (Sandbox Code Playgroud)

在JNR库界面中具有另一个功能

public int doSomething(Fn fn);
Run Code Online (Sandbox Code Playgroud)

用作doSomethingC代码接受中的包装int(*)(void const*, void const**, void**)。但是每当我创建一个回调时:

new Fn() { int call() { ... } };
Run Code Online (Sandbox Code Playgroud)

并将其传递给doSomething我的JNR库接口的方法,我得到运行时错误:

java.lang.ExceptionInInitializerError

    Caused by:
    java.lang.IllegalArgumentException: unsupported closure parameter type class [Ljnr.ffi.Pointer;
        at jnr.ffi.provider.jffi.NativeClosureProxy.newProxyFactory(NativeClosureProxy.java:109)
        at jnr.ffi.provider.jffi.NativeClosureFactory.newClosureFactory(NativeClosureFactory.java:84)
        at jnr.ffi.provider.jffi.NativeClosureManager.initClosureFactory(NativeClosureManager.java:71)
        at jnr.ffi.provider.jffi.NativeClosureManager.getClosureFactory(NativeClosureManager.java:49)
        at jnr.ffi.provider.jffi.NativeClosureManager.newClosureSite(NativeClosureManager.java:81)
        at jnr.ffi.provider.jffi.InvokerTypeMapper.getToNativeConverter(InvokerTypeMapper.java:68)
        at jnr.ffi.provider.jffi.InvokerTypeMapper.getToNativeType(InvokerTypeMapper.java:143)
        at jnr.ffi.mapper.CachingTypeMapper.lookupAndCacheToNativeType(CachingTypeMapper.java:71)
        at jnr.ffi.mapper.CachingTypeMapper.getToNativeType(CachingTypeMapper.java:43)
        at jnr.ffi.mapper.CompositeTypeMapper.getToNativeType(CompositeTypeMapper.java:34)
        at jnr.ffi.provider.jffi.InvokerUtil.getParameterTypes(InvokerUtil.java:185)
        at jnr.ffi.provider.jffi.AsmLibraryLoader.generateInterfaceImpl(AsmLibraryLoader.java:125)
        at jnr.ffi.provider.jffi.AsmLibraryLoader.loadLibrary(AsmLibraryLoader.java:59)
        at jnr.ffi.provider.jffi.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:43)
        at jnr.ffi.LibraryLoader.load(LibraryLoader.java:265)
        at jnr.ffi.LibraryLoader.load(LibraryLoader.java:244)
Run Code Online (Sandbox Code Playgroud)

我使用Pointer怎么了?

wks*_*wks 0

如果是C调用Java,我认为不可能从仅仅一个C指针给Java一个实际的Java数组。

首先,Java 数组对象具有内置长度,但 C 指针值本身不包含上限。C 通常使用诸如零终止字符串或传递两个参数(ptr、len)之类的约定。

其次,Java 数组必须在使用之前填充(即不能偷懒)。这意味着加载指向数组的所有指针,这可能效率低下。这还需要使用已知的数组长度来完成。

我建议在访问数组指针时自己在 Java 中进行指针算术。这需要了解特定于平台的内存布局(例如,指针数组中一个指针元素的长度),但所有本机接口都是特定于平台的。