首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JNR采用指针参数的回调/闭包

JNR采用指针参数的回调/闭包
EN

Stack Overflow用户
提问于 2014-10-05 12:02:37
回答 2查看 919关注 0票数 5

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

代码语言:javascript
复制
int fn(void const*, void const**, void**)

转换成一些C函数。我在Java端声明了嵌套在JNR库接口中的回调为:

代码语言:javascript
复制
public static interface Fn {
  @Delegate public int call(Pointer a, Pointer[] b, Pointer[] c);
}

使用JNR库接口中的另一个函数

代码语言:javascript
复制
public int doSomething(Fn fn);

在接受int(*)(void const*, void const**, void**)的C代码中充当doSomething的包装器。但每当我创建回调时:

代码语言:javascript
复制
new Fn() { int call() { ... } };

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

代码语言:javascript
复制
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有什么问题吗

EN

回答 2

Stack Overflow用户

发布于 2015-09-14 14:22:44

如果是C调用Java,我不认为仅仅通过一个C指针就可以给Java提供一个真正的Java数组。

首先,Java数组对象有一个内置的长度,但C指针值本身并不包含该长度的上限。C通常使用一些约定,比如以零结尾的字符串,或者传递两个参数(ptr,len)。

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

我建议在访问指向数组的指针时,在Java中自己做指针运算。

票数 0
EN

Stack Overflow用户

发布于 2016-05-27 22:27:22

就像wks说的,

首先,

数组对象有一个内置的长度,但是C指针值本身并不包含这个长度的上限。C通常使用一些约定,比如以零结尾的字符串,或者传递两个参数(ptr,len)。

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

一旦void const**void**参数等同于未知大小的数组,您就应该对这些参数使用jnr.ffi.byref.PointerByReference,如下所示:

代码语言:javascript
复制
public int call(Pointer a, PointerByReference b, PointerByReference c);

那么你方法的用法应该是这样的:

代码语言:javascript
复制
Pointer a = new Pointer.wrap(Runtime.getSystemRuntime(), variable);
PointerByReference b = new PointerByReference();
PointerByReference c = new PointerByReference();
call(a, b, c);
Pointer bValue = b.getValue();

为了进一步管理数据,您应该确切地知道您正在处理的是哪种数据。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26199515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档