pedoc
pedoc

Reputation: 93

how to transform byte[] to struct (contains a byte[] member and length member)

i have a struct define as:

[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi,Pack = 1)]
internal struct Message
{
    [MarshalAs(UnmanagedType.U1, SizeConst = 1)]
    public byte age;
    [MarshalAs(UnmanagedType.U2, SizeConst = 2)]
    public ushort length;
    [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1,SizeConst = 502)]
    public byte[] data;
}

payload received via udp,when received byte[],need to be converted to struct. data length specified as 502,but actually it should be the length member value indicating the data length,if remove the SizeConst attr, the code will throw Marshal exception at Marshal.SizeOf(typeof(T)).

public static T ToStruct<T>(this byte[] buf)
{
    var lth = Marshal.SizeOf(typeof(T));
    if (lth > buf.Length) return default(T);
    var ptr = Marshal.AllocHGlobal(lth);
    Marshal.Copy(buf, 0, ptr, lth);
    var structure = Marshal.PtrToStructure(ptr, typeof(T));
    Marshal.FreeHGlobal(ptr);
    return (T)structure;
}

exception info:

System.ArgumentException: Type 'Itms.Agent.IotBox.TieTa.Entity.Message' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed.

i know this is very simple to handle in c/c++, but C# doesn't have a similar approach. any help?

Upvotes: 2

Views: 123

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062560

when received byte[],need to be converted to struct. data length specified as 502,but actually it should be the length member value indicating the data length

that's too complex for simple marshal operations. You'll probably have to serialize/deserialize manually, i.e. something like:

byte[] payload = ...
var age = payload[0];
var len = (payload[1] << 8) | payload[2]; // invert depending on endianness
byte[] data = len == 0 ? Array.Empty<byte>() : new byte[len];
Buffer.BlockCopy(payload, 3, data, len);
var msg = new Message(age, len, data);

This would mean you could remove all the attributes, as you're not using any marshalling features. Also... the length field seems kinda redundant, since it is simply duplicating the array's length.

Upvotes: 1

Related Questions