簡體   English   中英

如何在 c#.net 中將結構轉換為字節數組,但僅在運行時定義結構大小

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM