我正在尝试从C struct
构建C#显式union
。显式结构是:
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct struct_1
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public uint[] All32;
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
public struct_2[] bits;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct struct_2
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] Var56;
}
这些是结构,我从All32
数组(intellisense显示'?')实例化之后无法访问uint
byte
,如下所示
Type structureType = typeof(struct_1);
byte[] b = new byte[4];
b[0] = 0xA0;
b[1] = 0x01;
b[2] = 0xF0;
b[3] = 0x00;
if (structureType != null)
{
try
{
GCHandle handle = GCHandle.Alloc(b, GCHandleType.Pinned);
struct_1 intpdObj = (struct_1)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), structureType);
handle.Free();
}
catch
{
}
}
答案 0 :(得分:1)
行。这是因为您在struct_2
内定义了一个数组,并且它是一个对象,因此当PtrToStructure
创建结构时,内存地址将被放在该位置内。你可以试试这个:
[StructLayout(LayoutKind.Explicit, Pack = 1)]
public struct struct_1
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray)]
public uint[] All32;
[FieldOffset(0)]
[MarshalAs(UnmanagedType.Struct)]
public struct_2 bits;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct struct_2
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public byte[] Var56;
}
答案 1 :(得分:1)
MarshalAs
属性不会改变.NET类/结构中数据的表示方式,它只会改变传递给其他代码时数据编组的方式。数组仍将是对数组的引用,并且它在那里变成了地狱。
您可以使用此方法覆盖两个不同类型的数组,但涉及一些严重的问题。最大的问题是所有阵列的元素数量都是相同的,但为阵列分配的内存量将是相同的。
以此联盟为例:
[StructLayout(LayoutKind.Explicit)]
public struct ArrayUnion
{
[FieldOffset(0)]
public byte[] bytes;
[FieldOffset(0)]
public int[] ints;
}
如果我使用100字节数组创建该结构的新实例,ints
数组也将声称其长度为100:
var u = new ArrayUnion { bytes = new byte[100] };
Console.WriteLine(u.ints.Length);
当然这是不正确的。如果我尝试访问ints
数组中前25个条目之后的任何内容,我可能会收到严重错误并崩溃。
您当然可以将这些内容包装到私有字段中并公开适当的方法。要小心你实际访问数据的方式......因为如果你弄错了,你将打破。
答案 2 :(得分:0)
为什么All32
是一个数组?如果你尝试这样的话会怎么样?
[StructLayout( LayoutKind.Explicit, Pack = 1 )]
public unsafe struct struct_1
{
[FieldOffset( 0 )]
public uint All32;
[FieldOffset( 0 )]
public fixed byte bits[4];
}
编辑:如果您确实希望All32
成为数组:
[StructLayout( LayoutKind.Explicit, Pack = 1 )]
public unsafe struct struct_1
{
[FieldOffset( 0 )]
public fixed uint All32[1];
[FieldOffset( 0 )]
public fixed byte bits[4];
}