Ανάγνωση ενός C / C ++ δομή δεδομένων σε C # από ​​έναν πίνακα byte

ψήφοι
65

Ποιος θα ήταν ο καλύτερος τρόπος για να γεμίσει ένα C # struct από ένα byte [] πίνακα, όπου τα δεδομένα ήταν από C C ++ struct /; Το struct 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 [] array;

Είμαι σήμερα να κάνει κάτι σαν το παρακάτω, αλλά αισθάνεται το είδος της 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();

Υπάρχει καλύτερος τρόπος για να επιτευχθεί αυτό;


Θα χρησιμοποιώντας την BinaryReaderτάξη προσφέρει καμία βελτίωση απόδοσης πάνω από καρφώνει τη μνήμη και τη χρήση Marshal.PtrStructure;

Δημοσιεύθηκε 05/08/2008 στις 22:19
πηγή χρήστη
Σε άλλες γλώσσες...                            


5 απαντήσεις

ψήφοι
88

Από ό, τι βλέπω σε αυτό το πλαίσιο, δεν χρειάζεται να αντιγράψετε SomeByteArrayσε ένα ρυθμιστικό. Πρέπει απλά να πάρετε τη λαβή από SomeByteArray, το pin αυτό, αντιγράψτε τα 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 
{
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try
    {
        T 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));
    }
}
Απαντήθηκε 05/08/2008 στις 22:29
πηγή χρήστη

ψήφοι
4

Εδώ είναι μια εξαίρεση ασφαλή έκδοση του αποδεκτή απάντηση :

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();
    }
}
Απαντήθηκε 24/01/2017 στις 18:40
πηγή χρήστη

ψήφοι
4

Προσέξτε για τα θέματα συσκευασίας. Στο παράδειγμα που έδωσε όλα τα πεδία είναι στα εμφανή τα αντισταθμιστικά οφέλη, διότι τα πάντα είναι στις 4 τα όρια byte, αλλά αυτό δεν είναι πάντα η περίπτωση. Visual C ++ πακέτα στις 8 όρια byte από προεπιλογή.

Απαντήθηκε 31/08/2008 στις 11:03
πηγή χρήστη

ψήφοι
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;
}   

Εχω αυτο

Απαντήθηκε 11/12/2011 στις 12:46
πηγή χρήστη

ψήφοι
0

Εάν έχετε ένα byte [] θα πρέπει να είναι σε θέση να χρησιμοποιούν την κλάση BinaryReader και ρυθμίστε τις τιμές στο NewStuff χρησιμοποιώντας τις διαθέσιμες μεθόδους ReadX.

Απαντήθηκε 05/08/2008 στις 22:24
πηγή χρήστη

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