簡體   English   中英

如何將C#字節數組轉換為結構化數據?

[英]How do I convert a C# byte array into structured data?

我通過USB將64字節數據包傳遞給微控制器。 在微控制器C代碼中,數據包具有結構,

typedef union
{
    unsigned char data[CMD_SIZE];
    cmd_get_t get;
    // plus more union options
} cmd_t;

typedef struct
{
    unsigned char cmd;          //!< Command ID
    unsigned char id;           //!< Packet ID
    unsigned char get_id;       //!< Get identifier
    unsigned char rfu[3];       //!< Reserved for future use
    union
    {
        unsigned char data[58];     //!< Generic data
        cmd_get_adc_t adc;          //!< ADC data
        // plus more union options
    } data;                     //!< Response data
} cmd_get_t;

typedef struct
{
    int16_t supply;
    int16_t current[4];
} cmd_get_adc_t;

在C#的PC端,我已經提供了一個函數,它將64字節數據包作為Byte []返回。 該函數使用Marshal.Copy將接收的數據復制到Byte []數組中。 然后我使用了表單的C#結構

[StructLayout(LayoutKind.Sequential, Pack=1)]
    public struct COMMAND_GET_ADC
    {
        public byte CommandID;
        public byte PacketID;
        public byte GetID;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
            public byte[] RFU;
        public short Supply;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
            public short[] Current;
    }

並再次使用Marshal.Copy將字節數組復制到結構中,以便我可以使用作為結構化數據,例如

COMMAND_GET_ADC cmd = (COMMAND_GET_ADC)RawDeserialize(INBuffer, 1, typeof(COMMAND_GET_ADC));
short supply = cmd.Supply;

public static object RawDeserialize(Byte[] rawData, int position, Type anyType)
{
    int rawsize = Marshal.SizeOf(anyType);
    if(rawsize > rawData.Length)
    {
        return null;
    }
    IntPtr buffer = Marshal.AllocHGlobal(rawsize);
    Marshal.Copy(rawData, position, buffer, rawsize);
    object retobj = Marshal.PtrToStructure(buffer, anyType);
    Marshal.FreeHGlobal(buffer);
    return retobj;
}

這只是感覺我正在制作大量的數據副本,並且它可能不是實現我想要的最有效的方式。 我還需要將結構化數據轉換回字節數組以獲取設備的命令。 我有一個使用相同過程的方法(即使用結構然后將其序列化為字節數組並將字節數組傳遞給寫入函數)。

還有更好的選擇嗎?

如果您可以使用不安全的代碼,則可以使用'fixed'關鍵字將字節數組轉換為指向結構的指針。

如果您自己調用本機DLL,則可以定義DllImport-s,以便它們直接返回並接受COMMAND_GET_ADC - 前提是您已正確表示結構。 框架本身應該照顧它。

如果你必須使用提供給你的方法使用的字節數組 - 那么我不知道,我從來沒有這樣的約束。 我總是嘗試以與本機dll相同的方式表示我的互操作性數據,我不記得我遇到了重大問題。

編輯:

[StructLayout(LayoutKind.Explicit)]
public struct COMMAND_GET
{
    [FieldOffset(0)]
    public byte CommandID;
    [FieldOffset(1)]
    public byte PacketID;
    [FieldOffset(2)]
    public byte GetID;
    [FieldOffset(3)]
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
    public byte[] RFU;
    [FieldOffset(6)]
    public ADC_Data Adc_data;
    [FieldOffset(6)]
    public SomeOther_Data other_data;
    [FieldOffset(6)]
    ....
}


[StructLayout(LayoutKind.Sequential, Pack=1)]
public struct ADC_Data
{
    public short Supply;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=4)]
    public short[] Current;
}

基本上你有FieldOffset(6),你在cmd_get_t中創建了類似數據聯合的聯合

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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