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

Java JNA传递结构,包含指向结构的指针和指向原语的指针,java,jna,Java,Jna,我正在使用JNA,并发现它非常直接地用于从本机库检索数据,但我很难理解如何以另一种方式进行检索,即将结构化数据传递给本机方法 我将使用我试图调用的库的一部分中的一个小示例 本机库typedef如下所示: typedef struct CreateInfo { int count; // Number of queue infos const QueueInfo* queues; // Zero-or-more queue info

我正在使用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实现可以如下所示(为了简洁起见,省略了字段顺序、构造函数等):

因此:

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

  • 如果我已经有一个
    QueueInfo
    数组,我可以简单地将指针设置为该数组的第一个元素吗?或者我是否需要使用
    Structure::toArray
    分配数组?这些结构除了默认构造函数之外没有其他构造函数,它们应该有吗

  • 我有队列优先级浮点数组,但如何设置指针?它应该是指针还是别的什么?浮点数[]

  • 我可以在SO和interwebs上找到很多问题,通常用于从本机库接收结构,但用于传递结构化数据的问题相对较少。我发现的例子都使用了不同的方法来解决同一个问题,这些方法看起来非常复杂,因为应该很简单(?),所以我对“正确”的方法感到迷茫

    我怀疑我没有提出正确的问题,这可能意味着我遗漏了关于JNA的一些基本信息


    希望有一些善良的灵魂能够指出上面幼稚的JNA代码的错误,以及如何在Java端用数据填充它。

    1-JNA映射

    映射被设计为直接将Java端类型与相应的本机端类型相关联。当这些映射所需的内存众所周知时,JNA工作得非常好。不幸的是,当要映射的本机内存量可变时,需要一些工作来分配和映射所需的本机内存。有几种方法可以做到这一点,不同级别的抽象/控制

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

    按照您在问题中定义
    QueueInfo
    的方式,这没有什么帮助。您只定义了一个Java端类,但是
    指针
    类暗示了一个本机内存指针。您应该修改类以扩展
    结构
    ,并在
    计数
    字段上使用
    公共
    。请注意,实例化此结构将仅为
    int
    指针
    分配本机内存。阵列本身的内存需要单独分配

    3-分配浮点数组

    正如我在评论中提到的,要为浮点数组分配本机内存:

    Memory buffer = new Memory(count * Native.getNativeSize(Float.TYPE));
    
    然后假设您定义了
    float[]buf
    ,您可以使用

    buffer.write(0L, buf, 0, count);
    
    然后,您可以使用
    buffer
    作为
    QueueInfo
    实例的
    priorities
    字段

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

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

    摘要

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


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

    因此,问题2的“标准”答案似乎是必须使用
    structure::toArray
    实例化一个结构数组,例如
    final QueueInfo[/queues=(QueueInfo[])new QueueInfo().toArray(size);对于(int n=0;n
    对#1的部分回答是“指向数组结构的指针”字段应该是
    结构。通过引用
    。相应地修改了JNA。#1:取决于你对愚蠢的定义#2:使用
    Structure.toArray()
    方法更方便,因为您不必从本机内存
    read()
    每个结构。您还可以使用
    指针
    ,并使用指针构造函数从适当的偏移量实例化结构#3:
    指针
    通常是一个很好的映射。最终得到的是一个本机分配的缓冲区,您可以使用
    指针.getFloatArray()
    来检索值。@DanielWiddis不确定“检索值”是什么意思?我不需要检索任何东西,我已经在Java代码中有了数据,我只需要将它作为结构中的字段传递给本机库。还是我没有领会你的意思?也许您可以提供一个wha的快速伪代码片段
    buffer.write(0L, buf, 0, count);