如何在C#中声明一个联合?

时间:2009-11-26 18:55:59

标签: .net interop

请注意以下示例代码:

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中定义)

3 个答案:

答案 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 ...

希望这可以帮到你, 最好的祝福, 汤姆。