[英]How to Convert structure to Byte array in c#.net but the structure size defined in runtime only
我有一個像下面這樣的結構
[StructLayout(LayoutKind.Sequential)]
public struct MyStructType
{
[MarshalAs(UnmanagedType.U1)]
public byte stx;
public UInt16 cmdId;
public UInt16 status;
public UInt16 pktNo;
[MarshalAs(UnmanagedType.U1)]
public byte contPkt;
[MarshalAs(UnmanagedType.U1)]
public byte dataoffset;
public UInt16 dataLength;
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)]
public byte[] data;
public UInt16 checkSum;
[MarshalAs(UnmanagedType.U1)]
public byte cr;
}
我嘗試使用以下代碼將此結構轉換為字節數組。
byte[] ConvertStructureToByteArray(MyStructType str)
{
int size = Marshal.SizeOf(str);
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(str, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
但我收到以下錯誤,因為他們不知道大小
類型“MyStructType”不能作為非托管結構進行封送; 無法計算出有意義的大小或偏移量。
問題是因為
public UInt16 dataLength;
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)]
public byte[] data;
dataLength 在運行時計算。 如何將此結構轉換為 ByteArray?
正如您已經注意到的, Marshal.SizeOf()
無法計算包含UnmanagedType.LPArray
byte
數組的結構的大小。 但是,這並不意味着您不能自己計算它。
但是,即使您這樣做,您也會得到Marshal.StructureToPtr
抱怨必須使用 SafeArray 或 ByValArray 的數據字段。
您應該在 MSDN 上檢查這一點,以了解如何將陣列從托管傳遞到非托管。 但是,對於包含在 struct 中的數組,似乎:
大小只能設置為常數
Protocol Buffer 是一種將數據序列化為二進制的簡單方法。 此外,它還支持模型更改、模型共享和其他幾個很酷的功能。
它有多種語言版本:
由於@Fab 提供的答案中指出的編組限制,添加提供解決方案的答案
public UInt16 dataLength;
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 6)]
public byte[] data;
編組實際上並沒有非常干凈地處理數組,因為它不會像您期望的那樣計算數組中每個元素的偏移量(即使使用提供的屬性,去計算!)。 由於您的結構很小,您可以執行以下操作來正確編組字節:
[StructLayout(LayoutKind.Sequential)]
public struct MyStructType
{
[MarshalAs(UnmanagedType.U1)]
public byte stx;
public UInt16 cmdId;
public UInt16 status;
public UInt16 pktNo;
[MarshalAs(UnmanagedType.U1)]
public byte contPkt;
[MarshalAs(UnmanagedType.U1)]
public byte dataoffset;
public UInt16 dataLength;
public MyDataArray data;
public UInt16 checkSum;
[MarshalAs(UnmanagedType.U1)]
public byte cr;
}
[StructLayout(LayoutKind.Sequential, Pack = 1, Size = Size)]
public struct MyDataArray
{
public const int Size = 6;
public byte Byte0;
public byte Byte1;
public byte Byte2;
public byte Byte3;
public byte Byte4;
public byte Byte5;
public MyDataArray(byte[] bytes) {
if (bytes == null || bytes.Length != Size)
throw new ArgumentOutOfRangeException(nameof(bytes));
Byte0 = bytes[0];
Byte1 = bytes[1];
Byte2 = bytes[2];
Byte3 = bytes[3];
Byte4 = bytes[4];
Byte5 = bytes[5];
}
public byte[] ToArray() {
return new byte[Size] { Byte0, Byte1, Byte2, Byte3, Byte4, Byte5 };
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.