как преобразовать byte [] в struct (содержит элемент byte [] и элемент length) - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть структура, определяемая как:

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

полезная нагрузка, полученная через udp , при получении байта [], должна быть преобразована в структуру.data длина указана как 502, но на самом деле это должно быть значение элемента length, указывающее длину данных. Если удалить атрибут SizeConst, код выдаст исключение Marshal в 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;
}

информация об исключении:

System.ArgumentException: тип 'Itms.Agent.IotBox.TieTa.Entity.Message' нельзя маршалировать как неуправляемую структуру;Никакой значимый размер или смещение не могут быть вычислены.

я знаю, что это очень просто обрабатывать в c / c ++, но C # не имеет подобного подхода.любая помощь?

1 Ответ

0 голосов
/ 18 декабря 2018

при получении байта [], необходимо преобразовать в struct.длина данных указана как 502, но на самом деле это должно быть значение элемента длины, указывающее длину данных

, которое слишком сложно для простых операций маршала.Вам, вероятно, придется сериализовать / десериализовать вручную, то есть что-то вроде:

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

Это будет означать, что вы можете удалить все атрибуты, так как вы не используете никаких функций сортировки.Кроме того ... поле length кажется излишним, поскольку оно просто дублирует длину массива.

...