这是我的 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];
}
items
在 get_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 - 如何授予应用程序(而非用户本身)对文件夹和文件的权限
flutter - 如何更新 flutterfire_web_sdk_version 以及如何启用
wordpress - 如何使用 WordPress Multisite 重定向特定站点的主页
sql - 从现有表创建 BigQuery 表,包括 _PARTITIONTIME