首页 > 解决方案 > JNA toArray() 重置结构字段?

问题描述

考虑以下 JNA 结构:

public class VkDeviceQueueCreateInfo extends VulkanStructure {
    public VkStructureType sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    public Pointer pNext;
    public int flags;
    public int queueFamilyIndex;
    public int queueCount;
    public Pointer pQueuePriorities;
}

sType字段是本机层用来标识结构类型的常量值。对于使用new.

但是,如果我们在为每个数组元素调用构造函数,使用 is分配此结构的数组toArray(),则将sType其重置为默认值。即它清除了领域!

无效的替代方案:

唯一可行的方法是关闭结构的自动读取:

public class VkDeviceQueueCreateInfo extends VulkanStructure {
    ...
    public VkDeviceQueueCreateInfo() {
        setAutoRead(false);
    }
}

(请注意,此结构用于写入本机层,不回读任何内容)。

这行得通,但它实际上在做什么?为什么 JNA 将结构重置为本机值时还没有?有没有办法在全局范围内关闭该字段的自动读取?

这对于单个结构来说不是什么大问题,但是在这个项目中,有数百个是从原生层生成的代码,其中大部分(但不是全部)都sType像上面的示例一样预先填充。显然,预先填充该字段不是要走的路,但有什么替代方案?是否需要使用上述小提琴重新生成每个结构?

编辑:深思熟虑后想到的另一个相关问题 - 结构中的数组类型呢?它们是否null被自动读取的东西重置?代码生成的结构初始化任何数组以调整结构的大小,例如public float[] colour = new float[4];

标签: javaarraysstructurejna

解决方案


您在正确的轨道上指出自动read()是这里问题的一部分。当您调用时,toArray()您(通常)将数组的内存支持更改为新的本机内存分配(自动分配将内存清零)。所以所有这些 0 都被加载到你的数组中。

为了方便起见,内部结构toArray()保留了第一个元素的值,但对其余元素不做任何事情,这些元素newInstance()在循环内使用实例化。这是导致您的问题的两行:

array[i] = newInstance(getClass(), memory.share(i*size, size));
array[i].conditionalAutoRead();

我的建议是让您toArray()在自己的VulkanStructure结构中覆盖其他人继承的结构。您可以复制现有代码并根据需要对其进行修改(例如,删除自动读取)。

或者,您可以重载一个toArray()传递结构集合的 a,并在将旧集合读取到新集合之前将其复制到支持内存上。toArray()或者,如果调用时原始内存支持足够大,则不会清除内存。因此,您可以分配自己的足够大的内存,useMemory()在第一个元素上使用以更改其支持,并复制支持的内存字节;并且它们将被自动读入新的数组版本。


推荐阅读