java - 如何使用二维指针通过 JNA 调用 C 函数?

这是我的 C 函数的签名:

typedef struct myitem_s {
    int a;
    int b;
} myitem_t;

int get_items(myitem_t** items);

在C程序中的用法是:

myitem_t* items = NULL;
int n = = get_items(&items);

for (int i = 0; i < n; ++i) {
    myitem_t* item = &items[i];
}

itemsget_items() 函数中分配,包含一个或多个 myitem_t 元素。

从 Java 代码我已经成功地做到了这一点:

Memory itemsPtr = new Memory(Native.POINTER_SIZE);
Pointer p = itemsPtr.getPointer(0);
int n = CLibrary.INSTANCE.get_items(p);

n 值有效,itemsPtr 已更新,因此我建议值也不错。现在我不知道如何使用它。还有其他方法吗?

最佳答案

您的代码有效,但是当 JNA 具有一些更高级别的构造时,您使用了很多较低级别的函数。

首先,C struct 可以用 JNA Structure 表示。

@FieldOrder({ "a", "b" })
class MyitemT extends Structure {
    public int a;
    public int b;
}

由于 native 代码正在处理内存分配,您所需要的只是指向它的指针。您可能需要 PointerByReference 而不是指针大小的内存分配。

PointerByReference pbr = new PointerByReference();

您希望从中获得的关键方法是 getPointer()(指向指针的指针)和 getValue()(指向的值)。

鉴于上述情况,将指向指针的指针传递给方法,该方法将分配内存并填充值。

使用您已有的映射(未显示但推断):

int n = CLibrary.INSTANCE.get_items(pbr.getPointer());

但是,您实际上应该映射 get_items() 以获取 PointerByReference 参数,然后您可以直接传递 items

此时,items.getValue() 是指向结构数组开头的指针。根据结构的大小 (item.size()),其他项将位于指针值的偏移量处。有多种方法可以做到这一点。

在你的情况下,因为你知道你只有一对整数,你可以跳过整个“结构”部分,只使用 items.getValue().getInt(0)items .getValue().getInt(4) 对于第一对;第二对是 8 和 12,等等。但更好的是,只需 items.getValue().getIntArray(0,n*2); 获取一个整数数组,只需将它们成对取出即可。

但这利用了内部细节。可能最像 JNA 的选择是使用 Structure.toArray() 创建一个 MyitemT 结构数组。如果您包含指针构造函数并使用该指针创建初始结构,Structure.toArray() 将使用该现有映射。然后你可以 read() 进入你的数组:

MyItemT item = new MyItemT(pbr.getValue());
MyItemT[] items = (MyItemT[]) item.toArray(n);
for (int i = 0; i < n; i++) { 
    items[i].read();
    // now you can see items[i].a and items[i].b
}

不要忘记最终释放 native 分配的内存,尽管 API 告诉您这样做!

https://stackoverflow.com/questions/72458275/

相关文章:

unity3d - Unity Microgame WebGL 上传不工作(500 内部服务器)

python - 异步 Pool.execute 与 Connection.execute

python - 根据另一个 df 中的列计算一个 df 中的行数

python - 如何授予应用程序(而非用户本身)对文件夹和文件的权限

python - SQLAlchemy 不插入默认值

flutter - 如何更新 flutterfire_web_sdk_version 以及如何启用

wordpress - 如何使用 WordPress Multisite 重定向特定站点的主页

sql - 从现有表创建 BigQuery 表,包括 _PARTITIONTIME

javascript - 未捕获的类型错误 : Failed to resolve module s

python - pydantic.error_wrappers.ValidationError :