无法从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
   {
   }
}

无法从c#的显式结构(联合)中访问变量

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];
}