Reputation: 93
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
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