gpt4 book ai didi

c# - 将 C# void* 转换为 byte[]

转载 作者:行者123 更新时间:2023-11-30 12:18:15 25 4
gpt4 key购买 nike

在 C# 中,我需要将 T[] 写入流,理想情况下没有任何额外的缓冲区。我有一个动态代码,可以将 T[](其中 T 是无对象结构)转换为 void* 并将其修复在内存中,效果很好。当流是一个文件时,我可以使用 native Windows API 直接传递 void *,但现在我需要写入一个采用 byte[] 的通用 Stream 对象。

问题:谁能建议一种黑客方法来创建一个虚拟数组对象,该对象实际上没有任何堆分配,而是指向一个已经存在的(和固定的)堆位置?

这是我需要的伪代码:

void Write(Stream stream, T[] buffer)
{
fixed( void* ptr = &buffer ) // done with dynamic code generation
{
int typeSize = sizeof(T); // done as well

byte[] dummy = (byte[]) ptr; // <-- how do I create this fake array?

stream.Write( dummy, 0, buffer.Length*typeSize );
}
}

更新:我在 this article 中详细描述了如何执行 fixed(void* ptr=&buffer) .我总是可以创建一个 byte[],将其固定在内存中,并进行从一个指针到另一个指针的不安全字节复制,然后将该数组发送到流中,但我希望避免不必要的额外分配和复制。

不可能?进一步思考后,byte[] 在堆中有一些元数据,其中包含数组维度和元素类型。简单地将引用(指针)传递给 T[] 作为 byte[] 可能不起作用,因为 block 的元数据仍然是 T[] 的元数据。即使元数据的结构相同,T[] 的长度也将远小于 byte[],因此托管代码对 byte[] 的任何后续访问都将生成不正确的结果。

请求@ Microsoft Connect 的功能请投票给this request , 希望 MS 会倾听。

最佳答案

这种代码永远无法以通用方式工作。它依赖于一个硬性假设,即 T 的内存布局是可预测且一致的。仅当 T 是简单值类型时才成立。暂时忽略字节顺序。如果 T 是引用类型,您就完蛋了,您将复制永远无法反序列化的跟踪句柄,您必须为 T 提供结构约束。

但这还不够,结构类型也不可复制。即使它们没有引用类型字段也不行,这是您无法约束的。内部布局由 JIT 编译器决定。它随意交换字段,选择一个字段正确对齐且结构值采用最小存储大小的字段。您要序列化的值只能由使用完全相同的 CPU 架构和 JIT 编译器版本运行的程序正确读取。

框架中已经有很多类可以完成您正在做的事情。最接近的匹配项是 .NET 4.0 MemoryMappedViewAccessor 类。它需要做同样的工作,使内存映射文件中的原始字节可用。那里的主力是 System.Runtime.InteropServices.SafeBuffer 类,用 Reflector 看看。不幸的是,您不能只复制类,它依赖于 CLR 来进行转换。话又说回来,再过一周就可以使用了。

关于c# - 将 C# void* 转换为 byte[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2570082/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com