代码之家  ›  专栏  ›  技术社区  ›  Yuri Astrakhan

将C#void*转换为字节[]

  •  3
  • Yuri Astrakhan  · 技术社区  · 15 年前

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

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

    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 );
        }
    }  
    

    更新: fixed(void* ptr=&buffer) 深入 this article . 我总是可以创建一个字节[],在内存中修复它,并将不安全的字节从一个指针复制到另一个指针,然后将该数组发送到流,但我希望避免不必要的额外分配和复制。

    不可能的

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

    4 回复  |  直到 14 年前
        1
  •  3
  •   Hans Passant    15 年前

    这种代码永远不能以通用方式工作。它依赖于一个硬假设,即T的内存布局是可预测和一致的。只有当T是一个简单的值类型时才是这样。暂时忽略endianness。如果T是一个引用类型,那么你就死定了,你将复制永远无法反序列化的跟踪句柄,你必须给T结构约束。

    框架中已经有很多类可以完成您正在做的事情。最接近的匹配是。NET 4.0 MemoryMappedViewAccessor类。它需要做同样的工作,使原始字节在内存映射文件中可用。那里的主力是系统。运行时。互操作服务。SafeBuffer类,看一看反射器。不幸的是,您不能只复制类,它依赖CLR进行转换。再说一次,离上市只有一周了。

        2
  •  0
  •   John Saunders    15 年前

    unsafe static void Write<T>(Stream stream, T[] buffer) where T : struct
    {
        System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc(buffer, System.Runtime.InteropServices.GCHandleType.Pinned);
        IntPtr address = handle.AddrOfPinnedObject();
        int byteCount = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)) * buffer.Length;
        byte* ptr = (byte*)address.ToPointer();
        byte* endPtr = ptr + byteCount;
        while (ptr != endPtr)
        {
            stream.WriteByte(*ptr++);
        }
        handle.Free();
    }
    
        3
  •  0
  •   Community CDub    8 年前

    查看我对相关问题的回答: What is the fastest way to convert a float[] to a byte[]?

    在其中,我临时将浮点数组转换为字节数组,而无需内存分配和复制。

    不幸的是,这种解决方案本身并不适合泛型。然而,你 将这种黑客技术与代码生成技术结合起来解决您的问题。

        4
  •  0
  •   nim    13 年前

    看这篇文章 Inline MSIL in C#/VB.NET and Generic Pointers 获取梦想代码的最佳方法:)

    推荐文章