请注意以下示例代码:
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: Could not load type 'AAA' from assembly 'Shunra.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=807fc02bc4ce69db' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.
失败
如何处理它?</ p>
感谢。
修改
BTW,这是由PInvokeTool创建的MINIDUMP_CALLBACK_INPUT结构互操作的精简版本(原始结构在DbgHelp.h中定义)
答案 0 :(得分:2)
问题在于,无论您为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;
...
}
编辑:澄清。
答案 1 :(得分:-1)
在我看来,你不能有两个偏移量为0的FieldOffsetAttribute。
确保您在MSDN库中查看其定义: http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.fieldoffsetattribute.aspx
答案 2 :(得分:-1)
我认为你需要在Struct中添加一个构造函数,以便实例化BBB和CCC类型,反过来,在每个其他结构BBB和CCC中,你还需要一个构造函数来实例化DDD类型。
struct DDD { [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 512, ArraySubType = UnmanagedType.I1)] byte[] x; } struct BBB { DDD x; public BBB(){ x = new DDD(); } } struct CCC { DDD x; ulong y; ulong z; public CCC(){ x = new DDD(); } } [StructLayout(LayoutKind.Explicit)] struct AAA { [FieldOffsetAttribute(0)] BBB a; [FieldOffsetAttribute(0)] CCC b; public AAA(){ a = new BBB(); b = new CCC(); } }
唯一的问题是struct DDD的实例化是未知的,因为你声明了一个字段x是一个byte []数组且大小未知,所以你必须根据自己的要求处理这个。也许传入参数,也许是一个指示数组大小的int ...
希望这可以帮到你, 最好的祝福, 汤姆。