You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法正确将C结构体映射到C#结构体问题求助

C#结构体映射56字节byte数组的修正方案

先梳理你当前代码的核心问题,再给出修正后的实现:

核心错误点

  • 类型不匹配:C中的uint16_t对应C#的ushort(2字节),你错误使用了uint(4字节),且搭配错误的UnmanagedType.U4,导致内存占用和解析错位。
  • Marshal配置错误:
    • Value字段C中是uint32_t,你用了UnmanagedType.I4(有符号int),应该用UnmanagedType.U4。
    • Name字段未指定SizeConst=16,Marshal无法确定数组长度。
    • 基础值类型(如uint)无需额外指定SizeConst,类型本身的字节大小已明确,多余配置反而可能引发解析问题。
  • pad字段类型冗余:C中char pad是1字节,C#用byte比char更直接,避免字符编码干扰。

修正后的C#结构体

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct ParameterResponse
{
    // uint32_t 对应 C# uint
    public uint Descriptor;
    public uint Value;
    public uint Minimum;
    public uint Maximum;
    public uint Default;

    // uint16_t 对应 C# ushort
    public ushort Next;
    public ushort Previous;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public char[] Units;

    public ushort Multiplier;
    public ushort Divisor;
    public ushort Base;
    public ushort Offset;

    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public char[] Link;

    // C中char pad为1字节,用byte更直观
    public byte pad;

    // 对应C中char[16],必须指定SizeConst
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public byte[] Name;

    // 构造函数参数类型对应修改
    public ParameterResponse(uint descriptor, uint value, uint minimum, uint maximum, uint defaultValue, 
                            ushort next, ushort previous, char[] units, ushort multiplier, ushort divisor, 
                            ushort baseValue, ushort offset, char[] link, byte padValue, byte[] name)
    {
        Descriptor = descriptor;
        Value = value;
        Minimum = minimum;
        Maximum = maximum;
        Default = defaultValue;
        Next = next;
        Previous = previous;
        Units = units;
        Multiplier = multiplier;
        Divisor = divisor;
        Base = baseValue;
        Offset = offset;
        Link = link;
        pad = padValue;
        Name = name;
    }
}

字节数组转结构体的正确实现

确保转换时使用Marshal类的内存操作,避免手动解析错误:

public static ParameterResponse ByteArrayToStruct(byte[] bytes)
{
    if (bytes.Length != Marshal.SizeOf(typeof(ParameterResponse)))
        throw new ArgumentException("字节数组长度与结构体大小不匹配");

    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    try
    {
        IntPtr ptr = handle.AddrOfPinnedObject();
        return (ParameterResponse)Marshal.PtrToStructure(ptr, typeof(ParameterResponse));
    }
    finally
    {
        handle.Free();
    }
}

验证步骤

  1. 调用Marshal.SizeOf(typeof(ParameterResponse)),确认返回值为56,与原C结构体大小一致。
  2. 用已知的测试字节数组转换,检查各字段值是否与预期匹配,尤其是Next、Previous等原uint16_t类型的字段,避免因字节错位导致的值异常。

内容的提问来源于stack exchange,提问作者Venky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:30:45