有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    如果您传递一个Pointer值,JNA不知道您实际上传递的是一个Structure或它们的一个数组,您需要确保在本机调用之前和之后调用Structure.write()

    如果您传递了StructureStructure[],那么JNA将自动处理同步。在Structure的情况下,JNA使用内部簿记来确定所传递的结构是否位于结构数组的头部