JNA从Java传递到C后未初始化的结构数组
我一直在使用JNA相对成功地从Java向我编写的一个小型C库进行本机函数调用。一旦您掌握了结构映射、内存管理和按引用传递的技巧,将结构或指针从一个传递到另一个非常有效
我现在正试图将一组结构从Java传递到C。以下是结构的C代码:
typedef struct key {
int length;
void *data;
} key_t;
我有Java中的匹配定义:
public class Key extends Structure {
public int length;
public Pointer data;
public Key() {
this.setFieldOrder(new String[] {"length", "data"});
}
public void setAsLong(long value) {
this.length = 8;
this.data = new Memory(this.length);
this.data.setLong(0, value);
}
public long longValue() {
return this.data != null ? this.data.getLong(0) : Long.MIN_VALUE;
}
};
如果我理解了文档和在线阅读的内容,我需要通过在Java端执行以下操作将数组创建为连续内存部分:
Key[] keys = new Key().toArray(2);
for (int i=0; i<2; i++) {
k.setAsLong(42+i);
}
到目前为止还不错。如果我使用Structure.toString()
转储Java中每个Key
结构的内容,这里的一切都如预期的那样。请注意,当我将单个Key
结构从Java传递到C时,有关设置为长值、为键内容分配内存等的代码工作正常。因此,这里我使用指向数组第一个元素的指针将数组传递给本机函数:
instance.foo(keys[0].getPointer(), keys.length);
我的C函数当然是这样定义的:
void foo(key_t *keys, size_t count) {
...;
}
数组正确到达了那里:C端的keys
指针与Java中的keys[0].getPointer()
地址相同,但不幸的是数组中每个结构的成员都是0/NULL
,正如GDB所指出的:
(gdb) print keys
$1 = (key_t *) 0x7fd7e82389e0
(gdb) print keys[0]
$2 = {length = 0, data = 0x0}
在这一点上,我真的不知道发生了什么。正如我所说,如果我只通过一个结构,它工作得很好,但这里没有办法。我能看到的唯一区别是Java本机方法签名,它使用Pointer
而不是Key[]
,但是当我使用数组时,我得到:
IllegalArgumentException: [Lfoo.bar.Key; is not a supported argument type (in method foo ...
谢谢
# 1 楼答案
如果您传递一个
Pointer
值,JNA不知道您实际上传递的是一个Structure
或它们的一个数组,您需要确保在本机调用之前和之后调用Structure.write()
如果您传递了
Structure
或Structure[]
,那么JNA将自动处理同步。在Structure
的情况下,JNA使用内部簿记来确定所传递的结构是否位于结构数组的头部