首頁 > 後端開發 > C++ > 如何有效率地將 C/C 位元組數組轉換為 C# 結構?

如何有效率地將 C/C 位元組數組轉換為 C# 結構?

Mary-Kate Olsen
發布: 2025-01-19 06:12:11
原創
1028 人瀏覽過

How to Efficiently Convert a C/C   Byte Array to a C# Structure?

從位元組數組讀取C/C 資料結構到C#

問題

此任務涉及將包含來自C/C 結構體資料的位元組數組轉換為對應的C#結構體。 C/C 結構體如下圖所示:

1

2

3

4

5

6

7

8

9

typedef struct OldStuff {

    CHAR Name[8];

    UInt32 User;

    CHAR Location[8];

    UInt32 TimeStamp;

    UInt32 Sequence;

    CHAR Tracking[16];

    CHAR Filler[12];

} OldStuff;

登入後複製

而C#結構體,名為NewStuff,定義如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

[StructLayout(LayoutKind.Explicit, Size = 56, Pack = 1)]

public struct NewStuff

{

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]

    [FieldOffset(0)]

    public string Name;

 

    [MarshalAs(UnmanagedType.U4)]

    [FieldOffset(8)]

    public uint User;

 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]

    [FieldOffset(12)]

    public string Location;

 

    [MarshalAs(UnmanagedType.U4)]

    [FieldOffset(20)]

    public uint TimeStamp;

 

    [MarshalAs(UnmanagedType.U4)]

    [FieldOffset(24)]

    public uint Sequence;

 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]

    [FieldOffset(28)]

    public string Tracking;

}

登入後複製

提出的解決方案

最初,考慮了一種比較繁瑣的方法,涉及固定記憶體並使用Marshal.PtrToStructure

1

2

3

4

5

6

7

8

9

10

int BufferSize = Marshal.SizeOf(typeof(NewStuff));

byte[] buff = new byte[BufferSize];

 

Array.Copy(SomeByteArray, 0, buff, 0, BufferSize);

 

handle = GCHandle.Alloc(buff, GCHandleType.Pinned);

 

MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));

 

handle.Free();

登入後複製

改進

經過進一步分析,確定原始方法中的緩衝區複製是不必要的。相反,直接的句柄固定就夠了:

1

2

3

4

5

6

7

8

9

10

11

12

GCHandle handle;

NewStuff MyStuff;

 

handle = GCHandle.Alloc(SomeByteArray, GCHandleType.Pinned);

try

{

    MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));

}

finally

{

    handle.Free();

}

登入後複製

此外,可以使用泛型甚至更簡單的版本(需要不安全切換):

  • 泛型:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

T ByteArrayToStructure<T>(byte[] bytes) where T : struct

{

    T stuff;

    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);

    try

    {

        stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));

    }

    finally

    {

        handle.Free();

    }

    return stuff;

}

登入後複製
  • 更簡單(不安全):

1

2

3

4

5

6

7

unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct

{

    fixed (byte* ptr = &bytes[0])

    {

        return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T));

    }

}

登入後複製

使用BinaryReader提高效能

雖然首選的解決方案涉及固定和Marshal.PtrToStructure,但在特定情況下,使用BinaryReader類別解析資料可能會提供效能優勢。但是,必須評估具體的實現以確定此類增益是否顯著。

以上是如何有效率地將 C/C 位元組數組轉換為 C# 結構?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板