JNA toArray() 重置结构字段?

JNA toArray() resets structure fields?

考虑以下 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.

创建的 class 的 单个 实例

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

无效的替代方案:

唯一似乎有效的方法是关闭结构的自动读取:

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

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

这有效,但它实际上在做什么?为什么 JNA 在结构还没有时将结构重置为原始值?有没有办法全局关闭该字段的自动读取?

这对于单个结构来说不是什么大问题,但在这个项目中有数百个代码是从本机层生成的,其中大部分(但不是全部)都带有 sType pre-如上例填充。很明显,预填充该字段不是可行的方法,但有什么替代方法呢?是否需要使用上述 fiddle 重新生成每个结构?

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

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

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

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

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

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