JNA 如何在要传递给本机库的结构中填充指向结构字段的指针?
JNA How to populate a pointer-to-structure field within a structure to be PASSED to the native library?
我需要将 JNA 结构传递给包含结构指针字段(可能包含零个或多个结构)的本机层。
这里是 'parent' 结构:
public class VkRenderPassCreateInfo extends Structure {
public int attachmentCount;
public VkAttachmentDescription.ByReference pAttachments;
}
(其他字段,@FieldOrder 和 ByReference/Value class 省略)
这里是 'child' 结构:
public class VkAttachmentDescription extends Structure {
public int flags;
// ... lots and lots of other simple fields
}
根据 JNA 文档 (here),指向数组的指针字段应该是 Structure.ByReference
字段。
根据其他帖子,填充此字段的标准方法是:
将字段初始化为引用结构
使用Structure::toArray
从字段中分配结构数组
填充数组
所以:
// Init structure fields
renderPass.pAttachments = new VkRenderPassCreateInfo.ByReference();
renderPass.attachmentCount = size;
// Allocate memory
VkAttachmentDescription[] attachments = (VkAttachmentDescription[]) renderPass.pAttachments.toArray(size);
// Populate array
for(int n = 0; n < size; ++n) {
attachments[n].flags = ...
// and so on for other fields
}
1 - 这是在结构中初始化和分配指向结构字段的指针的正确方法吗?似乎有很多废话?
2 - 以上适用于摆弄大小的结构,但我正在处理的一些结构有大量的字段、子结构等。我原以为我可以构建一个 JNA 结构数组在 Java 端并将它们直接设置到父结构中,但是 toArray
方法意味着我 有 然后将所有内容复制到生成的数组?是否有一种 better/simpler 方法意味着我不必创建和复制我在 Java 端基本上已经拥有的数据?
3 - JNA 提供了一个 StringArray
助手 class 来处理结构中字符串数组的类似情况:
// Array of strings maintained on the Java side
List<String> strings = ...
// Nice and easy means of populating the JNA structure
structure.pStrings = new StringArray(strings.toArray(String[]::new));
...
// Send the data
library.fireandForget(structure);
这是我试图用上面的结构代码实现的某种东西,但显然仅适用于字符串情况 - 是否还有其他类似的助手我错过了?
请注意上面是传递结构到本地层,我没有试图检索任何东西。
编辑 1: 只是为了限定这个问题的要点——尽管上面的方法有效,但除了最微不足道的情况外,它会导致所有样板代码的错误数量。我正在努力找出 simplest/best 方法来构建要传递给本机方法的复杂结构图。似乎缺少示例或教程,或者也许我只是没有问正确的问题(?)任何指向示例、教程或传递包含指向其他结构的指针的结构的示例代码的指针都是 very 赞赏。
编辑 2: 所以我尝试了很多方法,当我调用本机库时,所有这些方法都会导致 Illegal memory access
错误。
我要发送的数据由应用程序构建 - 它可以是构建器模式、用户的选择等。在任何情况下,结果都是我随后需要的 VkAttachmentDescription
列表在 'parent' VkRenderPassCreateInfo
.
中作为指向结构字段的指针发送
在 Java 端使用 JNA VkAttachmentStructure
的原因是这些结构中的一些包含大量字段。也就是说,调用 Structure::toArray
然后逐个字段地填充结果数组是站不住脚的:代码量会很大,容易出错且难以更改(例如,忘记复制新字段)。我可以创建 另一个 class 来抽象 JNA class 但这只会解决问题。
这是代码的作用:
// Application builds the attachments
final List<VkAttachmentDescription> attachments = ...
...
// At some point we then send the render pass including the attachments
// Populate the render pass descriptor
final VkRenderPassCreateInfo info = new VkRenderPassCreateInfo();
info.pAttachments = ??? <--- what?
// ... other fields
// Send the descriptor
library.sendRenderPass(info);
尝试 1:天真地将指向结构的指针设置为数组:
final VkRenderPassCreateInfo info = new VkRenderPassCreateInfo();
final var array = attachments.toArray(VkAttachmentDescription.ByReference[]::new);
info.pAttachments = array[0];
library.sendRenderPass(info);
结果是内存访问错误,没想到还能这样!
尝试 2:使用 Structure::toArray(int) 并将字段设置为第一个元素
final VkAttachmentDescription.ByReference[] array = (VkAttachmentDescription.ByReference[]) new VkAttachmentDescription.ByReference().toArray(attachments.size());
for(int n = 0; n < size; ++n) {
array[n] = attachments.get(n);
}
info.pAttachments = array[0];
library.sendRenderPass(info);
同样的结果。
尝试 3:使用 Structure::toArray(数组)
Structure
中有一个替代的 toArray
方法,它接受一个数组,但它似乎与调用整数版本没有任何不同?
尝试 4:逐字段复制
final VkAttachmentDescription.ByReference[] array = (VkAttachmentDescription.ByReference[]) new VkAttachmentDescription.ByReference().toArray(attachments.size());
for(int n = 0; n < size; ++n) {
array[n].field = attachments.get(n).field;
// ...lots of other fields
}
info.pAttachments = array[0];
library.sendRenderPass(info);
这有效但很讨厌。
我显然完全遗漏了一些关于 JNA 的信息。我的主要症结在于 Structure::toArray
创建了一个 空 结构数组,必须逐个字段填充,但我 已经 具有包含所有内容的结构数组 - 如何将指向结构字段的指针设置为该数组(即相当于 StringArray
助手)?在我的脑海里这似乎是一件很简单的事情,但我根本找不到任何例子来说明如何做我想做的事(除了那些逐字段复制的琐碎例子)。
另一件困扰我的事情是,父结构字段必须是 ByReference
,这意味着代码中的每个其他结构都必须是引用?再次感觉我做错了。
您需要解决的问题(以及 Illegal memory access
错误的来源)是接受数组的 C 端代码期望 Pointer
到 连续内存块。在C中,只需要第一个元素的内存地址,加上大小偏移;要访问数组[1],您会找到数组[0] 的内存并按结构的大小进行偏移。
在你的例子中,你已经为这个块中的每个结构分配了非连续内存:
// Application builds the attachments
final List<VkAttachmentDescription> attachments = ...
每个 VkAttachmentDescription
都映射到它自己的内存,尝试读取第一个结构末尾的内存会导致错误。如果您无法控制实例化这些 VkAttachmentDescription
对象时使用的内存,您最终将重复您的内存需求,并且必须将本机内存从非连续块复制到连续块。
编辑添加: 正如您在其他答案中指出的那样,如果您只在 Java 侧使用 VkAttachmentDescription
结构并且没有将其传递给 C 函数,则本机内存可能尚未写入。以下基于 Pointer.get*()
方法的解决方案直接从 C 内存读取,因此它们需要在某些时候进行 write()
调用。
假设您别无选择,只能从 List<VkAttachmentDescription>
开始,您需要做的第一件事就是分配 C 需要的连续内存。让我们得到我们需要的字节大小:
int size = attachments.size();
int bytes = attachments.get(0).size();
我们需要分配 size * bytes
内存。
这里有两个选择:直接使用 Memory
对象(Pointer
的子class)分配内存或使用 Structure.toArray
。对于直接分配:
Memory mem = new Memory(size * bytes);
如果我们这样定义引用,我们可以直接使用mem
作为Pointer
:
public class VkRenderPassCreateInfo extends Structure {
public int attachmentCount;
public Pointer pAttachments;
}
那就简单了:
info.pAttachments = mem;
现在剩下的就是将字节从非连续内存复制到分配的内存中。我们可以一个字节一个字节地做(在C端更容易看到字节级别发生了什么):
for (int n = 0; n < size; ++n) {
Pointer p = attachments.get(n).getPointer();
for (int b = 0; b < bytes; ++b) {
mem.setByte(n * bytes + b, p.getByte(b));
}
}
或者我们可以一个结构一个结构地做:
for (int n = 0; n < size; ++n) {
byte[] attachment = attachments.get(n).getPointer().getByteArray(0, bytes);
mem.write(n * bytes, attachment, 0, bytes);
}
(性能权衡:数组实例化开销与 Java<-->C 调用。)
现在缓冲区已写入,您可以将其发送到 C,它需要结构数组,它不会知道区别...字节就是字节!
编辑添加: 我认为可以使用 useMemory()
更改本机内存后备,然后直接写入新的(连续的)位置。此代码未经测试,但我怀疑它可能确实有效:
for (int n = 0; n < size; ++n) {
attachments.get(n).useMemory(mem, n * bytes);
attachments.get(n).write();
}
就我个人而言,由于我们只是复制已经存在的内容,我更喜欢这种基于 Memory
的映射。然而...有些码农是受虐狂
如果你想多一点 "type safe" 你可以在结构中使用 ByReference
class 声明并使用 toArray()
创建结构数组。
您已经在代码中列出了一种使用 ByReference 类型创建数组的方法。这行得通,或者您也可以使用(默认的 ByValue)类型创建它,然后在稍后将指针提取到第一个元素以在将其分配给结构字段时创建 ByReference 类型:
VkAttachmentDescription[] array =
(VkAttachmentDescription[]) new VkAttachmentDescription().toArray(attachments.size());
那你可以这样设置:
info.pAttachments = new VkAttachmentDescription.ByReference(array[0].getPointer());
在这种情况下,将值从列表(由单独分配的内存块支持的结构)复制到数组(连续内存)有点复杂,因为内存映射的类型更窄,但它遵循与 Memory
映射相同的模式。您发现的一种方法是手动复制结构的每个元素! (呃。)另一种可能使您免于某些 copy/paste 错误的方法是使用反射(JNA 在幕后所做的事情)。这也是很多工作,并且重复了 JNA 所做的工作,因此它很丑陋且容易出错。但是,仍然可以将原始本机字节从非连续内存块复制到连续内存块。 (在这种情况下......为什么不直接进入 Memory
但我的偏见正在显现。)您可以像 Memory
示例中那样迭代字节,如下所示:
for (int n = 0; n < size; ++n) {
Pointer p = attachments.get(n).getPointer();
Pointer q = array[n].getPointer();
for (int b = 0; b < bytes; ++b) {
q.setByte(b, p.getByte(b));
}
}
或者您可以像这样以块的形式读取字节:
for (int n = 0; n < size; ++n) {
byte[] attachment = attachments.get(n).getPointer().getByteArray(0, bytes);
array[n].getPointer().write(0, attachment, 0, bytes);
}
请注意,我尚未测试此代码;它写入本机端而不是 Java 结构,所以我认为它会按原样工作,但您可能需要在上述循环结束时调用 array[n].read()
以从 C 读取到 Java 以防有一个我不知道的内置 Java 到 C 副本。
回应您的 "parent structure field has to be ByReference":如上所示,Pointer
映射有效并允许更多的灵活性,但代价是 "type safety" 并且可能(或不)"readability"。你不需要在其他地方使用 ByReference
正如我在 toArray()
中展示的那样你只需要它用于结构字段(你可以将它定义为 Pointer
并完全消除需要 ByReference
... 但如果你这样做,为什么不直接复制到 Memory
缓冲区?我在这里打败了马!)。
最后,如果您知道最终将拥有多少元素(或该数字的上限),理想的解决方案是在一开始就使用连续内存实例化数组。然后,无需创建 VkAttachmentDescription
的新实例,您只需从数组中获取一个预先存在的实例即可。如果您过度分配并且不全部使用它们也没关系,只要您从一开始就连续使用它们。你传递给 C 的只是结构的#和第一个的地址,它不关心你是否有额外的字节。
这是一个执行上述结构复制方法的静态助手:
/**
* Allocates a contiguous memory block for the given JNA structure array.
* @param structures Structures array
* @return Contiguous memory block or <tt>null</tt> for an empty list
* @param <T> Structure type
*/
public static <T extends Structure> Memory allocate(T[] structures) {
// Check for empty case
if(structures.length == 0) {
return null;
}
// Allocate contiguous memory block
final int size = structures[0].size();
final Memory mem = new Memory(structures.length * size);
// Copy structures
for(int n = 0; n < structures.length; ++n) {
structures[n].write(); // TODO - what is this actually doing? following line returns zeros unless write() is invoked
final byte[] bytes = structures[n].getPointer().getByteArray(0, size);
mem.write(n * size, bytes, 0, bytes.length);
}
return mem;
}
助手可用于填充指向结构字段的指针,例如:
info.pAttachments = StructureHelper.allocate(attachments.toArray(VkAttachmentDescription[]::new));
info.attachmentCount = attachments.size();
似乎 可以工作,但我担心复制循环中似乎需要 write
。没有这个,从结构中提取的 byte[]
是零。 write
实际上在做什么?文档说复制到本机内存,但我无法弄清楚实际代码在做什么。
之后我应该释放这段内存吗?
是否有任何替代方法来获取结构内存?
我需要将 JNA 结构传递给包含结构指针字段(可能包含零个或多个结构)的本机层。
这里是 'parent' 结构:
public class VkRenderPassCreateInfo extends Structure {
public int attachmentCount;
public VkAttachmentDescription.ByReference pAttachments;
}
(其他字段,@FieldOrder 和 ByReference/Value class 省略)
这里是 'child' 结构:
public class VkAttachmentDescription extends Structure {
public int flags;
// ... lots and lots of other simple fields
}
根据 JNA 文档 (here),指向数组的指针字段应该是 Structure.ByReference
字段。
根据其他帖子,填充此字段的标准方法是:
将字段初始化为引用结构
使用
Structure::toArray
从字段中分配结构数组
填充数组
所以:
// Init structure fields
renderPass.pAttachments = new VkRenderPassCreateInfo.ByReference();
renderPass.attachmentCount = size;
// Allocate memory
VkAttachmentDescription[] attachments = (VkAttachmentDescription[]) renderPass.pAttachments.toArray(size);
// Populate array
for(int n = 0; n < size; ++n) {
attachments[n].flags = ...
// and so on for other fields
}
1 - 这是在结构中初始化和分配指向结构字段的指针的正确方法吗?似乎有很多废话?
2 - 以上适用于摆弄大小的结构,但我正在处理的一些结构有大量的字段、子结构等。我原以为我可以构建一个 JNA 结构数组在 Java 端并将它们直接设置到父结构中,但是 toArray
方法意味着我 有 然后将所有内容复制到生成的数组?是否有一种 better/simpler 方法意味着我不必创建和复制我在 Java 端基本上已经拥有的数据?
3 - JNA 提供了一个 StringArray
助手 class 来处理结构中字符串数组的类似情况:
// Array of strings maintained on the Java side
List<String> strings = ...
// Nice and easy means of populating the JNA structure
structure.pStrings = new StringArray(strings.toArray(String[]::new));
...
// Send the data
library.fireandForget(structure);
这是我试图用上面的结构代码实现的某种东西,但显然仅适用于字符串情况 - 是否还有其他类似的助手我错过了?
请注意上面是传递结构到本地层,我没有试图检索任何东西。
编辑 1: 只是为了限定这个问题的要点——尽管上面的方法有效,但除了最微不足道的情况外,它会导致所有样板代码的错误数量。我正在努力找出 simplest/best 方法来构建要传递给本机方法的复杂结构图。似乎缺少示例或教程,或者也许我只是没有问正确的问题(?)任何指向示例、教程或传递包含指向其他结构的指针的结构的示例代码的指针都是 very 赞赏。
编辑 2: 所以我尝试了很多方法,当我调用本机库时,所有这些方法都会导致 Illegal memory access
错误。
我要发送的数据由应用程序构建 - 它可以是构建器模式、用户的选择等。在任何情况下,结果都是我随后需要的 VkAttachmentDescription
列表在 'parent' VkRenderPassCreateInfo
.
在 Java 端使用 JNA VkAttachmentStructure
的原因是这些结构中的一些包含大量字段。也就是说,调用 Structure::toArray
然后逐个字段地填充结果数组是站不住脚的:代码量会很大,容易出错且难以更改(例如,忘记复制新字段)。我可以创建 另一个 class 来抽象 JNA class 但这只会解决问题。
这是代码的作用:
// Application builds the attachments
final List<VkAttachmentDescription> attachments = ...
...
// At some point we then send the render pass including the attachments
// Populate the render pass descriptor
final VkRenderPassCreateInfo info = new VkRenderPassCreateInfo();
info.pAttachments = ??? <--- what?
// ... other fields
// Send the descriptor
library.sendRenderPass(info);
尝试 1:天真地将指向结构的指针设置为数组:
final VkRenderPassCreateInfo info = new VkRenderPassCreateInfo();
final var array = attachments.toArray(VkAttachmentDescription.ByReference[]::new);
info.pAttachments = array[0];
library.sendRenderPass(info);
结果是内存访问错误,没想到还能这样!
尝试 2:使用 Structure::toArray(int) 并将字段设置为第一个元素
final VkAttachmentDescription.ByReference[] array = (VkAttachmentDescription.ByReference[]) new VkAttachmentDescription.ByReference().toArray(attachments.size());
for(int n = 0; n < size; ++n) {
array[n] = attachments.get(n);
}
info.pAttachments = array[0];
library.sendRenderPass(info);
同样的结果。
尝试 3:使用 Structure::toArray(数组)
Structure
中有一个替代的 toArray
方法,它接受一个数组,但它似乎与调用整数版本没有任何不同?
尝试 4:逐字段复制
final VkAttachmentDescription.ByReference[] array = (VkAttachmentDescription.ByReference[]) new VkAttachmentDescription.ByReference().toArray(attachments.size());
for(int n = 0; n < size; ++n) {
array[n].field = attachments.get(n).field;
// ...lots of other fields
}
info.pAttachments = array[0];
library.sendRenderPass(info);
这有效但很讨厌。
我显然完全遗漏了一些关于 JNA 的信息。我的主要症结在于 Structure::toArray
创建了一个 空 结构数组,必须逐个字段填充,但我 已经 具有包含所有内容的结构数组 - 如何将指向结构字段的指针设置为该数组(即相当于 StringArray
助手)?在我的脑海里这似乎是一件很简单的事情,但我根本找不到任何例子来说明如何做我想做的事(除了那些逐字段复制的琐碎例子)。
另一件困扰我的事情是,父结构字段必须是 ByReference
,这意味着代码中的每个其他结构都必须是引用?再次感觉我做错了。
您需要解决的问题(以及 Illegal memory access
错误的来源)是接受数组的 C 端代码期望 Pointer
到 连续内存块。在C中,只需要第一个元素的内存地址,加上大小偏移;要访问数组[1],您会找到数组[0] 的内存并按结构的大小进行偏移。
在你的例子中,你已经为这个块中的每个结构分配了非连续内存:
// Application builds the attachments
final List<VkAttachmentDescription> attachments = ...
每个 VkAttachmentDescription
都映射到它自己的内存,尝试读取第一个结构末尾的内存会导致错误。如果您无法控制实例化这些 VkAttachmentDescription
对象时使用的内存,您最终将重复您的内存需求,并且必须将本机内存从非连续块复制到连续块。
编辑添加: 正如您在其他答案中指出的那样,如果您只在 Java 侧使用 VkAttachmentDescription
结构并且没有将其传递给 C 函数,则本机内存可能尚未写入。以下基于 Pointer.get*()
方法的解决方案直接从 C 内存读取,因此它们需要在某些时候进行 write()
调用。
假设您别无选择,只能从 List<VkAttachmentDescription>
开始,您需要做的第一件事就是分配 C 需要的连续内存。让我们得到我们需要的字节大小:
int size = attachments.size();
int bytes = attachments.get(0).size();
我们需要分配 size * bytes
内存。
这里有两个选择:直接使用 Memory
对象(Pointer
的子class)分配内存或使用 Structure.toArray
。对于直接分配:
Memory mem = new Memory(size * bytes);
如果我们这样定义引用,我们可以直接使用mem
作为Pointer
:
public class VkRenderPassCreateInfo extends Structure {
public int attachmentCount;
public Pointer pAttachments;
}
那就简单了:
info.pAttachments = mem;
现在剩下的就是将字节从非连续内存复制到分配的内存中。我们可以一个字节一个字节地做(在C端更容易看到字节级别发生了什么):
for (int n = 0; n < size; ++n) {
Pointer p = attachments.get(n).getPointer();
for (int b = 0; b < bytes; ++b) {
mem.setByte(n * bytes + b, p.getByte(b));
}
}
或者我们可以一个结构一个结构地做:
for (int n = 0; n < size; ++n) {
byte[] attachment = attachments.get(n).getPointer().getByteArray(0, bytes);
mem.write(n * bytes, attachment, 0, bytes);
}
(性能权衡:数组实例化开销与 Java<-->C 调用。)
现在缓冲区已写入,您可以将其发送到 C,它需要结构数组,它不会知道区别...字节就是字节!
编辑添加: 我认为可以使用 useMemory()
更改本机内存后备,然后直接写入新的(连续的)位置。此代码未经测试,但我怀疑它可能确实有效:
for (int n = 0; n < size; ++n) {
attachments.get(n).useMemory(mem, n * bytes);
attachments.get(n).write();
}
就我个人而言,由于我们只是复制已经存在的内容,我更喜欢这种基于 Memory
的映射。然而...有些码农是受虐狂
如果你想多一点 "type safe" 你可以在结构中使用 ByReference
class 声明并使用 toArray()
创建结构数组。
您已经在代码中列出了一种使用 ByReference 类型创建数组的方法。这行得通,或者您也可以使用(默认的 ByValue)类型创建它,然后在稍后将指针提取到第一个元素以在将其分配给结构字段时创建 ByReference 类型:
VkAttachmentDescription[] array =
(VkAttachmentDescription[]) new VkAttachmentDescription().toArray(attachments.size());
那你可以这样设置:
info.pAttachments = new VkAttachmentDescription.ByReference(array[0].getPointer());
在这种情况下,将值从列表(由单独分配的内存块支持的结构)复制到数组(连续内存)有点复杂,因为内存映射的类型更窄,但它遵循与 Memory
映射相同的模式。您发现的一种方法是手动复制结构的每个元素! (呃。)另一种可能使您免于某些 copy/paste 错误的方法是使用反射(JNA 在幕后所做的事情)。这也是很多工作,并且重复了 JNA 所做的工作,因此它很丑陋且容易出错。但是,仍然可以将原始本机字节从非连续内存块复制到连续内存块。 (在这种情况下......为什么不直接进入 Memory
但我的偏见正在显现。)您可以像 Memory
示例中那样迭代字节,如下所示:
for (int n = 0; n < size; ++n) {
Pointer p = attachments.get(n).getPointer();
Pointer q = array[n].getPointer();
for (int b = 0; b < bytes; ++b) {
q.setByte(b, p.getByte(b));
}
}
或者您可以像这样以块的形式读取字节:
for (int n = 0; n < size; ++n) {
byte[] attachment = attachments.get(n).getPointer().getByteArray(0, bytes);
array[n].getPointer().write(0, attachment, 0, bytes);
}
请注意,我尚未测试此代码;它写入本机端而不是 Java 结构,所以我认为它会按原样工作,但您可能需要在上述循环结束时调用 array[n].read()
以从 C 读取到 Java 以防有一个我不知道的内置 Java 到 C 副本。
回应您的 "parent structure field has to be ByReference":如上所示,Pointer
映射有效并允许更多的灵活性,但代价是 "type safety" 并且可能(或不)"readability"。你不需要在其他地方使用 ByReference
正如我在 toArray()
中展示的那样你只需要它用于结构字段(你可以将它定义为 Pointer
并完全消除需要 ByReference
... 但如果你这样做,为什么不直接复制到 Memory
缓冲区?我在这里打败了马!)。
最后,如果您知道最终将拥有多少元素(或该数字的上限),理想的解决方案是在一开始就使用连续内存实例化数组。然后,无需创建 VkAttachmentDescription
的新实例,您只需从数组中获取一个预先存在的实例即可。如果您过度分配并且不全部使用它们也没关系,只要您从一开始就连续使用它们。你传递给 C 的只是结构的#和第一个的地址,它不关心你是否有额外的字节。
这是一个执行上述结构复制方法的静态助手:
/**
* Allocates a contiguous memory block for the given JNA structure array.
* @param structures Structures array
* @return Contiguous memory block or <tt>null</tt> for an empty list
* @param <T> Structure type
*/
public static <T extends Structure> Memory allocate(T[] structures) {
// Check for empty case
if(structures.length == 0) {
return null;
}
// Allocate contiguous memory block
final int size = structures[0].size();
final Memory mem = new Memory(structures.length * size);
// Copy structures
for(int n = 0; n < structures.length; ++n) {
structures[n].write(); // TODO - what is this actually doing? following line returns zeros unless write() is invoked
final byte[] bytes = structures[n].getPointer().getByteArray(0, size);
mem.write(n * size, bytes, 0, bytes.length);
}
return mem;
}
助手可用于填充指向结构字段的指针,例如:
info.pAttachments = StructureHelper.allocate(attachments.toArray(VkAttachmentDescription[]::new));
info.attachmentCount = attachments.size();
似乎 可以工作,但我担心复制循环中似乎需要 write
。没有这个,从结构中提取的 byte[]
是零。 write
实际上在做什么?文档说复制到本机内存,但我无法弄清楚实际代码在做什么。
之后我应该释放这段内存吗?
是否有任何替代方法来获取结构内存?