ホームページ > バックエンド開発 > C++ > C/C バイト配列を C# 構造体に効率的に変換するにはどうすればよいですか?

C/C バイト配列を C# 構造体に効率的に変換するにはどうすればよいですか?

Mary-Kate Olsen
リリース: 2025-01-19 06:12:11
オリジナル
956 人が閲覧しました

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>
ログイン後にコピー

NewStuff という名前の C# 構造は次のように定義されます:

<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 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート