观察以下示例代码:
struct DDD
{
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 512, ArraySubType = UnmanagedType.I1)]
byte[] x;
}
struct BBB
{
DDD x;
}
struct CCC
{
DDD x;
ulong y;
ulong z;
}
[StructLayout(LayoutKind.Explicit)]
struct AAA
{
[FieldOffsetAttribute(0)]
BBB a;
[FieldOffsetAttribute(0)]
CCC b;
}
不幸的是,无法加载AAA
,尝试执行new AAA()
失败,并出现System.TypeLoadException:无法从程序集'加载类型'AAA' Shunra.Common,Version=1.0.0.0,Culture=neutral,PublicKeyToken=807fc02bc4ce69db',因为它在偏移量 0 处包含一个对象字段,该对象字段未正确对齐或与非对象字段重叠。
如何应对?
谢谢。
编辑:
顺便说一句,这是 PInvokeTool 创建的 MINIDUMP_CALLBACK_INPUT 结构互操作的精简版本(原始结构在 DbgHelp.h 中定义)
最佳答案
问题是,无论您为 MarshalAsAttribute 指定什么,数组就是数组,就是托管对象。为了使您的代码正常工作,您必须摆脱托管数组。为此,您有两种选择:
选项 1:
将数组转换为固定大小的缓冲区,这意味着将 DDD 的定义更改为:
unsafe struct DDD {
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 512, ArraySubType = UnmanagedType.I1)]
fixed byte x[512];
}
(我不确定是否需要 MarshalAsAttribute,但我对此表示怀疑。)
现在您使用的是不安全的结构,因此您必须使用/unsafe 开关进行编译。
选项 2:
将数组转换为 512 字节的成员。最简单的方法是使用 64 个长整型:
struct DDD {
long x1;
long x2;
long x3;
...
}
编辑:澄清。
关于.net - 如何在 C# 中声明联合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1805179/