为了账号安全,请及时绑定邮箱和手机立即绑定

从字节数组中读取C#中的C / C ++数据结构

从字节数组中读取C#中的C / C ++数据结构

UYOU 2019-08-12 16:29:28
从字节数组中读取C#中的C / C ++数据结构从byte []数组填充C#结构的最佳方法是什么,其中数据来自C / C ++结构?C结构看起来像这样(我的C很生锈):typedef OldStuff {     CHAR Name[8];     UInt32 User;     CHAR Location[8];     UInt32 TimeStamp;     UInt32 Sequence;     CHAR Tracking[16];     CHAR Filler[12];}并填写这样的东西:[StructLayout(LayoutKind.Explicit, Size = 56, Pack = 1)]public struct NewStuff{     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]     [FieldOffset(0)]     public string Name;     [MarshalAs(UnmanagedType.U4)]     [FieldOffset(8)]     public uint User;     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]     [FieldOffset(12)]     public string Location;     [MarshalAs(UnmanagedType.U4)]     [FieldOffset(20)]     public uint TimeStamp;     [MarshalAs(UnmanagedType.U4)]     [FieldOffset(24)]     public uint Sequence;     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]     [FieldOffset(28)]     public string Tracking;}什么是复制OldStuff到的最佳方式NewStuff,如果OldStuff作为byte []数组传递?我现在正在做类似以下的事情,但感觉有点笨重。GCHandle handle;NewStuff MyStuff;int BufferSize = Marshal.SizeOf(typeof(NewStuff));byte[] buff = new byte[BufferSize];Array.Copy(SomeByteArray, 0, buff, 0, BufferSize);handle = GCHandle.Alloc(buff, GCHandleType.Pinned);MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));handle.Free();有没有更好的方法来实现这一目标?使用BinaryReader该类可以提供超过内存和使用的任何性能提升Marshal.PtrStructure吗?
查看完整描述

3 回答

?
泛舟湖上清波郎朗

TA贡献1818条经验 获得超3个赞

从我在该上下文中看到的内容,您不需要复制SomeByteArray到缓冲区中。您只需要从中获取句柄SomeByteArray,固定它,IntPtr使用PtrToStructure然后释放来复制数据。无需复印件。

那将是:

NewStuff ByteArrayToNewStuff(byte[] bytes){
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try
    {
        NewStuff stuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));
    }
    finally
    {
        handle.Free();
    }
    return stuff;}

通用版本:

T ByteArrayToStructure<T>(byte[] bytes) where T: struct {
    T stuff;
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try
    {
        stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    }
    finally
    {
        handle.Free();
    }
    return stuff;}

更简单的版本(需要unsafe切换):

unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct{
    fixed (byte* ptr = &bytes[0])
    {
        return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T));
    }}


查看完整回答
反对 回复 2019-08-12
?
ibeautiful

TA贡献1993条经验 获得超5个赞

public static T ByteArrayToStructure<T>(byte[] bytes) where T : struct{
    var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try {
        return (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    }
    finally {
        handle.Free();
    }}


查看完整回答
反对 回复 2019-08-12
?
LEATH

TA贡献1936条经验 获得超6个赞

注意包装问题。在示例中,您给出了所有字段都处于明显的偏移量,因为一切都在4字节边界上,但情况并非总是如此。默认情况下,Visual C ++打包为8字节边界。


查看完整回答
反对 回复 2019-08-12
  • 3 回答
  • 0 关注
  • 470 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信