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

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

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

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

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

問題

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

<code class="language-c++">typedef struct OldStuff {
    CHAR Name[8];
    UInt32 User;
    CHAR Location[8];
    UInt32 TimeStamp;
    UInt32 Sequence;
    CHAR Tracking[16];
    CHAR Filler[12];
} OldStuff;</code>
登入後複製

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

<code class="language-csharp">[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;
}</code>
登入後複製

提出的解決方案

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

<code class="language-csharp">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();</code>
登入後複製

改進

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

<code class="language-csharp">GCHandle handle;
NewStuff MyStuff;

handle = GCHandle.Alloc(SomeByteArray, GCHandleType.Pinned);
try
{
    MyStuff = (NewStuff)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(NewStuff));
}
finally
{
    handle.Free();
}</code>
登入後複製

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

  • 泛型:
<code class="language-csharp">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;
}</code>
登入後複製
  • 更簡單(不安全):
<code class="language-csharp">unsafe T ByteArrayToStructure<T>(byte[] bytes) where T : struct
{
    fixed (byte* ptr = &bytes[0])
    {
        return (T)Marshal.PtrToStructure((IntPtr)ptr, typeof(T));
    }
}</code>
登入後複製

使用BinaryReader提高效能

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

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

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