目标是让以下结构在 C# (.net 8.0) 中工作
[StructLayout(LayoutKind.Explicit, Size = 257, Pack = 1)]
public struct MyFrame
{
[FieldOffset(0)] public byte valueA;
[FieldOffset(1)] public byte valueB;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 254)]
[FieldOffset(2)] public byte[] valueArray;
[FieldOffset(256)] public byte valueC;
}
程序编译但在初始化期间抛出错误消息。
系统.TypeLoadException H结果=0x80131522 Message=无法从程序集“MyAssembly,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“MyFrame”,因为它在偏移量 2 处包含一个对象字段,该对象字段未正确对齐或与非对象字段重叠。 来源=MyAssemböy 堆栈跟踪: 在 MyAssembly.MyClass..ctor() ...
我的理解是,使用 1 的包装尺寸应该是可能的。 如果我将 valueArray 从偏移量 8 处开始,它会编译并运行,但我想将其放在 2 处。
理想情况下,我也想将其扩展为这样
[StructLayout(LayoutKind.Explicit, Size = 258, Pack = 1)]
public struct MyFrame
{
[FieldOffset(0)] public byte valueA;
[FieldOffset(1)] public byte valueB;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 254)]
[FieldOffset(2)] public byte[] valueArray;
[FieldOffset(256)] public byte valueC;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 257)]
[FieldOffset(0)] public byte[] rawBytes;
}
我该如何解决这个问题?
不能有重叠的引用类型对象,因此不能让数组与其他任何对象重叠。重叠是托管版本中的问题,而不是非托管版本中的问题。
它会在这里重叠,因为
FieldOffset
也会影响托管版本。
但是你不需要使用
LayoutKind.EXplicit
,你可以使用Sequential
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct MyFrame
{
public byte valueA;
public byte valueB;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 254)]
public byte[] valueArray;
public byte valueC;
}