jna - JNA 2 维数组
问题描述
JNA 2 维数组
我的 C 函数是
void func(void** bufs, int numBufs);
Tye C 代码需要一个指向字节数组的指针数组。func()
知道每个字节数组的长度并用数据填充它们。
这个 JNA 签名是什么?
我已经为这个看似简单的问题挣扎了两天,但没有破解它。
在 Java 方面,我DirectBuffer bufs[]
的目的是让 C 函数填充bufs[]
数据。
我曾期望我可以将 JNA 签名声明为
public static native boolean func(Pointer[] bufs, int numBufs);
然后构造一个 Java 指针数组,每个指针是new Pointer(db.address());
但是,虽然我可以构造指针的 java 数组,但我得到了错误:
java.lang.IllegalArgumentException: class [Lcom.sun.jna.Pointer; is not a supported argument type (in method func in class SomeLib)
我已经进行了长时间的实验,但一无所获。我查看了 StackOver flow 上的所有 JNA 示例,但没有一个完全适合。
我正在通过 Maven 使用 JNA
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.3.1</version>
</dependency>
任何帮助将不胜感激。
解决方案
你很近。不幸的是,非原始数组到 C 的映射只能以一种方式工作……您可以将检索到的内存映射到 Java 数组,但不能将 Java 数组发送到 C(原始数组除外)。
这种限制的原因是在 C 中,数组是连续的内存块。要访问数组的第二个元素,只需偏移等于第一个元素大小的字节数。但是传递给 C 函数的参数只是指向数组开头的指针。
所以你的映射func()
应该使用Pointer
数组参数。
您没有描述如何构造Pointer[]
数组,但是通过调用分配每个数组new Pointer()
会产生分散在本机内存中而不是连续的指针。
基本上有两种方法可以确保您拥有连续的内存,具体取决于您想要的抽象级别。
一种低级方法是创建一个对象,为您的数组(可能)Memory
分配足够的空间,然后使用适当的偏移倍数将您的数组映射到该对象。然后将对象传递给 C 函数。Pointer
new Memory(Native.POINTER_SIZE * numBufs)
setPointer()
Native.POINTER_SIZE
Memory
Memory
更高级别的方法是将 Pointer 包装在 JNAStructure
中,使用该Structure.toArray()
方法为您进行连续数组分配。所以你可以有这个:
public class Foo extends Structure {
public Pointer bar;
}
然后创建数组:
Foo[] array = (Foo[]) new Foo().toArray(numBufs);
此时,您有一个(连续的)本机内存数组映射到 JNA 的Pointer
类型。现在您只需将这些指向指针的指针分配给附加到数据的指针:
for (int i = 0; i < numBufs; i++) {
// Assign Pointer to corresponding DirectBuffer
array[i].bar = bufs[i];
}
然后你应该能够通过传递第一个元素的指针将数组传递给 C:
func(array[0].bar, numBufs);
// or equivalently
func(array[0].getPointer(), numBufs);
推荐阅读
- r - 如何从字符串中提取数字,包括数字之前的所有文本
- php - 如何在 WordPress 中将数据库表中的每条记录注册为简码
- grafana - 限制对特定 CloudWatch 仪表板的访问
- gradle - 如何从命令行配置 JaCoCo Gradle 插件
- cordova - TypeError: Object(...) is not a function at AndroidPermissions.requestPermission
- objective-c - UIWebView 在尝试打开另一个应用程序的 URL 时显示“无法显示 URL”,但它在 Safari 中有效
- wix - 如何在重大升级期间使用 Wix 工具集显式删除 dll
- javascript - Flash 播放器图表未在打印时显示
- python - 发生数据库更改时,有没有办法向 MQTT mosquitto 代理发送消息?
- continuous-integration - travis CI 测试通过后如何退出构建