Vra

Wat sou die beste manier om 'n C # struct van 'n byte [] skikking waar die data was van 'n C / C ++ struct vul wees?

: die C struct sou so iets (my C is baie verroes) kyk
typedef OldStuff {
    CHAR Name[8];
    UInt32 User;
    CHAR Location[8];
    UInt32 TimeStamp;
    UInt32 Sequence;
    CHAR Tracking[16];
    CHAR Filler[12];
}

En sou so iets te vul:

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

Wat is die beste manier om OldStuff kopieer na NewStuff, as OldStuff in werking getree het as byte [] skikking?

Ek is op die oomblik iets soos die volgende te doen, maar dit voel soort van clunky.

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

Is daar 'n beter manier om dit te bewerkstellig?


Sou die gebruik van die BinaryReader klas bied 'n opvoering winste oor pinning die geheue en die gebruik van Marshal.PtrStructure?

Was dit nuttig?

Oplossing

Van wat ek kan sien in hierdie konteks, het jy nie nodig het om SomeByteArray kopieer na 'n buffer. Jy hoef net die handvatsel te kry van SomeByteArray, pen dit, kopieer die IntPtr data met behulp van PtrToStructure en dan vry te laat. Nie nodig vir 'n afskrif.

Dit sou wees:

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

generiese weergawe:

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

Eenvoudiger weergawe (vereis unsafe skakelaar):

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

Ander wenke

Hier is 'n uitsondering veilig weergawe van die aanvaar antwoord :

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

Wees op die uitkyk vir die verpakking kwessies. In die voorbeeld het jy al die velde is by die hand liggend neutraliseer, want alles is op 4 byte grense maar dit sal nie altyd die geval wees. Visual C ++ pakke op 8 byte grense by verstek.

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

Het hierdie

As jy 'n byte [] moet jy in staat wees om die BinaryReader klas gebruik en stel waardes op NewStuff met behulp van die beskikbare ReadX metodes.

Gelisensieer onder: CC-BY-SA met toeskrywing
Nie verbonde aan StackOverflow
scroll top