Bir bayt diziden C # C okuma / C ++ veri yapısı

oy
65

Hangi veriler bir C / C ++ yapı oldu bir bayt [] diziden bir C # yapı doldurmak için en iyi yolu olurdu? C yapı (benim C çok paslı) böyle bir şey görünecektir:

typedef OldStuff {
    CHAR Name[8];
    UInt32 User;
    CHAR Location[8];
    UInt32 TimeStamp;
    UInt32 Sequence;
    CHAR Tracking[16];
    CHAR Filler[12];
}

Ve böyle bir şey doldururdu:

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

Kopyalamak için en iyi yolu nedir OldStuffiçin NewStuffise, OldStuffbyte [] dizi olarak kabul edildi?

Şu anda aşağıdaki gibi bir şey yapıyorum, ama gene de oldukça aksak hissediyor.

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

Bunu gerçekleştirmek için daha iyi bir yolu var mı?


Kullanarak misiniz BinaryReadersınıf bellek iğneleme ve üzerinden herhangi bir performans avantajları sağlıyor Marshal.PtrStructure?

Oluştur 05/08/2008 saat 22:19
kaynak kullanıcı
Diğer dillerde...                            


5 cevaplar

oy
88

Ben bu bağlamda Görebildiğimiz kadarıyla, kopyalamak gerekmez SomeByteArraybir tampon içine. Sadece gelen ele almak gerekiyor SomeByteArray, sabitleyin kopyalamak IntPtrkullanarak veri PtrToStructureve sonra serbest bırakın. Bir kopyasını gerek yok.

Olurdu:

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

Jenerik sürümü:

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

Daha basit sürümü (gerektirir unsafeanahtarı):

unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
    fixed (byte* ptr = &bytes[0])
    {
        return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T));
    }
}
Cevap 05/08/2008 saat 22:29
kaynak kullanıcı

oy
4

İşte bir istisna güvenli sürümüdür kabul edilen yanıt :

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();
    }
}
Cevap 24/01/2017 saat 18:40
kaynak kullanıcı

oy
4

paketleme konularında dikkat edin. Örnekte her şeyin 4 bayt sınırları ama bu her zaman böyle olmayacak çünkü tüm alanları belirgin uzaklıklar altındadır verdi. Varsayılan olarak 8 bayt sınırları paketleri Visual C ++.

Cevap 31/08/2008 saat 11:03
kaynak kullanıcı

oy
3
object ByteArrayToStructure(byte[] bytearray, object structureObj, int position)
{
    int length = Marshal.SizeOf(structureObj);
    IntPtr ptr = Marshal.AllocHGlobal(length);
    Marshal.Copy(bytearray, 0, ptr, length);
    structureObj = Marshal.PtrToStructure(Marshal.UnsafeAddrOfPinnedArrayElement(bytearray, position), structureObj.GetType());
    Marshal.FreeHGlobal(ptr);
    return structureObj;
}   

Al bunu

Cevap 11/12/2011 saat 12:46
kaynak kullanıcı

oy
0

Bir byte [] varsa BinaryReader sınıfını kullanın ve kullanılabilir ReadX yöntemler kullanılarak NewStuff değerlerini ayarlamak gerekir.

Cevap 05/08/2008 saat 22:24
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more