简体   繁体   English

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

[英]How to call C function through JNA with 2d pointer?

Here is the signature of my C function :这是我的 C 函数的签名:

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

int get_items(myitem_t** items);

The usage in a C program is::在 C 程序中的用法是:

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

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

items is allocated in the get_items() function and contains one or more myitem_t elements. itemsget_items()函数中分配并包含一个或多个myitem_t元素。

From Java code I have succeeded in doing this:从Java代码我已经成功地做到了这一点:

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

The n value is valid, itemsPtr is updated so I suggest value is good also. n值有效, itemsPtr已更新,因此我建议值也不错。 Now I have no idea of how to use it.现在我不知道如何使用它。 Is there another way of doing it?还有另一种方法吗?

Your code works but you're using a lot of lower level functions when JNA has some higher level constructs.您的代码有效,但是当 JNA 具有一些更高级别的构造时,您正在使用许多较低级别的函数。

First, the C struct can be represented by a JNA Structure .首先,C struct可以由 JNA Structure表示。

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

Since the native code is handling the memory allocation, all you need is the pointer to it.由于本机代码正在处理内存分配,因此您所需要的只是指向它的指针。 Rather than a pointer-sized memory allocation, you probably want a PointerByReference .您可能需要一个PointerByReference ,而不是指针大小的内存分配。

PointerByReference pbr = new PointerByReference();

The key methods you want from this are getPointer() (the pointer to the pointer) and getValue() (the pointed-to value).您需要的关键方法是getPointer() (指向指针的指针)和getValue() (指向的值)。

Given the above, pass the pointer-to-the-pointer to the method, which will allocate the memory and populate the value.鉴于上述情况,将指向指针的指针传递给方法,该方法将分配内存并填充值。

Using the mapping you already have (not shown but inferred):使用您已经拥有的映射(未显示但推断):

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

However, you should actually map get_items() to take a PointerByReference argument and then you can just pass items directly.但是,您实际上应该映射get_items()以获取PointerByReference参数,然后您可以直接传递items

At this point, items.getValue() is a Pointer to the start of your array of structures.此时, items.getValue()Pointer结构数组开头的指针。 Additional items would be at offsets of the pointer value based on the size of the structure ( item.size() ).根据结构的大小( item.size() ),其他项目将位于指针值的偏移量处。 There are multiple ways of getting at that.有多种方法可以做到这一点。

In your case since you know you just have pairs of ints, you could skip the whole "structure" part and just use items.getValue().getInt(0) and items.getValue().getInt(4) for the first pair;在你的情况下,因为你知道你只有成对的整数,你可以跳过整个“结构”部分,只使用items.getValue().getInt(0)items.getValue().getInt(4)作为第一对; 8 and 12 for the second pair, etc. But even better, just items.getValue().getIntArray(0,n*2);第二对为 8 和 12,依此类推。但更好的是items.getValue().getIntArray(0,n*2); fetches an array of integers, just pull them out by pairs.获取一个整数数组,只需将它们成对拉出即可。

But that takes advantage of internal details.但这利用了内部细节。 Probably the most JNA-ish choice is to use Structure.toArray() to create an array of your MyitemT structures.可能最适合 JNA 的选择是使用Structure.toArray()来创建MyitemT结构的数组。 If you include a pointer constructor and create the initial structure using that pointer, Structure.toArray() uses that existing mapping.如果您包含一个指针构造函数并使用该指针创建初始结构,则Structure.toArray()使用该现有映射。 You can then read() into your array:然后,您可以将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
}

Don't forget to eventually release the native-allocated memory however the API tells you to!不要忘记最终释放本机分配的内存,但 API 会告诉你!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM