JNA传递的结构,其中包含指向结构的指针和指向原语的指针

时间:2019-03-11 17:23:31

标签: java jna

我正在使用JNA并发现它非常简单,可以从本机库中检索数据,但是却难以理解如何进行另一种处理,即将结构化数据传递给本机方法。

我将使用尝试调用的库中的一个小例子。

本机库typedef如下:

typedef struct CreateInfo {
    int count;                    // Number of queue infos
    const QueueInfo* queues;      // Zero-or-more queue info structures
} CreateInfo;

typedef struct QueueInfo {
    int count;                    // Number of queue priorities
    const float* priorities;      // 'array' of queue priorities
} QueueInfo;

因此,我们有一个CreateInfo,它引用了多个QueueInfo,每个数字都包含一个浮点值列表。

这些结构的朴素JNA实现可能如下(为简洁起见,省略了字段顺序,构造函数等):

public class CreateInfo extends Structure {
    public int count;
    public QueueInfo.ByReference queues;
}

public QueueInfo extends Structure {
    int count;
    public Pointer priorities;
}

所以:

  1. JAN映射(故意)是幼稚的,但是它们真的很愚蠢吗?如果是这样,逻辑类型是什么?

  2. 如果我已经有一个QueueInfo数组,我可以简单地将指针设置为该数组的第一个元素吗?还是我必须使用Structure::toArray分配数组?除了默认结构以外,这些结构没有其他构造函数吗?

  3. 我有队列优先级的float数组,但是如何设置指针?它实际上应该是指针还是其他?浮点数[]?

对于从本地库中接收的结构,我通常会在SO和互连网上发现很多问题,而对于传递结构化数据的问题相对较少。而且我发现所有示例都针对同一问题使用了不同的方法,这些问题对于应该非常简单的方法(?)来说似乎非常复杂,所以我对“正确”的方法不知所措。

我怀疑我没有问正确的问题,这可能意味着我缺少有关JNA的基本知识。

希望有一个善良的灵魂可以指出上面朴素的JNA代码有什么问题,以及如何用Java端的数据填充它。

1 个答案:

答案 0 :(得分:1)

1-JNA映射

映射被设计为直接将Java端类型与相应的本机端类型相关联。当这些映射所需的内存众所周知时,JNA可以很好地工作。不幸的是,当要映射的本机内存量可变时,这需要一些工作来分配和映射所需的本机内存。可以通过几种不同的抽象/控制级别来执行此操作。

2-已经拥有QueueInfo [](第1部分)

使用您在问题中定义QueueInfo的方式,它没有帮助。您仅定义了Java端类,但是Pointer类隐含了本机内存指针。您应该修改您的类以扩展Structure,并在public字段上使用count。请注意,实例化此结构将仅为intPointer分配本机内存。阵列本身的内存需要单独分配。

3-分配浮点数组

正如我在评论中提到的,one way of doing this是为float数组分配本机内存:

Memory buffer = new Memory(count * Native.getNativeSize(Float.TYPE));

然后假设您已定义float[] buf,则可以使用以下命令将其复制到本地内存中

buffer.write(0L, buf, 0, count);

然后可以将buffer用作priorities实例的QueueInfo字段。

2-已经拥有QueueInfo [](第2部分)

现在要问的是,除非您知道自己有一个连续的C边数组,否则不能将指针设置为第一个元素。您的选择是使用Structure::toArray分配内存(然后填充每个元素),或者分别创建(连续的)指针数组,并从单独分配的结构中复制Pointer值。对于toArray变量,如果直接在生成的数组中设置值,则不需要指针构造函数,但是指针构造函数可使复制(从一个本机内存块到另一个本机内存块)的复制变得更加容易。

摘要

选项1:使用QueueInfo方法为float数组实例化单独的Pointer.write()结构。创建一个以float[]作为参数并设置count并如上所述分配和设置priorities变量的构造函数可能会有所帮助。然后,为Pointer结构创建一个CreateInfo s数组,并复制每个元素的引用指针。

选项2:使用Structure::toArray创建一个结构数组来分配本机内存;然后遍历此结构,并在适当的索引处直接创建QueueInfo结构。