我正在使用JNR并尝试传递一个具有以下C等价签名的回调函数:
int fn(void const*, void const**, void**)转换成一些C函数。我在Java端声明了嵌套在JNR库接口中的回调为:
public static interface Fn {
@Delegate public int call(Pointer a, Pointer[] b, Pointer[] c);
}使用JNR库接口中的另一个函数
public int doSomething(Fn fn);在接受int(*)(void const*, void const**, void**)的C代码中充当doSomething的包装器。但每当我创建回调时:
new Fn() { int call() { ... } };并将其传递给我的JNR库接口的doSomething方法,我得到运行时错误:
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)我使用Pointer有什么问题吗
发布于 2015-09-14 14:22:44
如果是C调用Java,我不认为仅仅通过一个C指针就可以给Java提供一个真正的Java数组。
首先,Java数组对象有一个内置的长度,但C指针值本身并不包含该长度的上限。C通常使用一些约定,比如以零结尾的字符串,或者传递两个参数(ptr,len)。
其次,在使用之前必须填充Java数组(即不是惰性的)。这意味着加载所有指向数组的指针,这可能是低效的。这也需要在已知数组长度的情况下完成。
我建议在访问指向数组的指针时,在Java中自己做指针运算。
发布于 2016-05-27 22:27:22
就像wks说的,
首先,
数组对象有一个内置的长度,但是C指针值本身并不包含这个长度的上限。C通常使用一些约定,比如以零结尾的字符串,或者传递两个参数(ptr,len)。
其次,在使用之前必须填充Java数组(即不是惰性的)。这意味着加载所有指向数组的指针,这可能是低效的。这也需要在已知数组长度的情况下完成。
一旦void const**和void**参数等同于未知大小的数组,您就应该对这些参数使用jnr.ffi.byref.PointerByReference,如下所示:
public int call(Pointer a, PointerByReference b, PointerByReference c);那么你方法的用法应该是这样的:
Pointer a = new Pointer.wrap(Runtime.getSystemRuntime(), variable);
PointerByReference b = new PointerByReference();
PointerByReference c = new PointerByReference();
call(a, b, c);
Pointer bValue = b.getValue();为了进一步管理数据,您应该确切地知道您正在处理的是哪种数据。
https://stackoverflow.com/questions/26199515
复制相似问题