无法从c#的显式结构(联合)中访问变量
本文关键字:联合 变量 访问 结构 | 更新日期: 2023-09-27 18:14:23
我正在尝试从C union
构建c#显式struct
。显式结构为:
[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
,这是从byte
数组实例化后的uint
(智能感知显示'?'),如下所示
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
{
}
}
OK。这是因为您在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;
}
MarshalAs
属性不会改变数据在。net类/结构中的表示方式,它只会改变数据传递给其他代码时的封送方式。数组仍然是对数组的引用,这一切都变成了地狱。
您可以使用此方法覆盖两个不同类型的数组,但其中涉及一些严重的问题。最大的问题是所有数组的元素数量是相同的,但是为数组分配的内存量是相同的。
以这个联合为例:
[StructLayout(LayoutKind.Explicit)]
public struct ArrayUnion
{
[FieldOffset(0)]
public byte[] bytes;
[FieldOffset(0)]
public int[] ints;
}
如果我用一个100字节的数组创建一个struct的新实例,ints
数组也会声明它的长度为100:
var u = new ArrayUnion { bytes = new byte[100] };
Console.WriteLine(u.ints.Length);
当然是不正确的。如果我然后尝试访问ints
数组中超过前25个条目的任何内容,我可能会得到一个严重的错误和崩溃。
当然,你可以将其中的一些内容包装到私有字段中,并公开适当的方法。只是要注意实际访问数据的方式……因为如果你写错了就会把东西弄坏
为什么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];
}