首页 >后端开发 >C++ >如何高效地将 C/C 字节数组转换为 C# 结构?

如何高效地将 C/C 字节数组转换为 C# 结构?

Mary-Kate Olsen
Mary-Kate Olsen原创
2025-01-19 06:12:11958浏览

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中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn