无法正确将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(); } }
验证步骤
- 调用
Marshal.SizeOf(typeof(ParameterResponse)),确认返回值为56,与原C结构体大小一致。 - 用已知的测试字节数组转换,检查各字段值是否与预期匹配,尤其是
Next、Previous等原uint16_t类型的字段,避免因字节错位导致的值异常。
内容的提问来源于stack exchange,提问作者Venky
相关产品推荐
相关产品推荐

