在联合内部使用引用类型和值类型成员的封送结构

时间:2014-01-06 13:52:10

标签: pinvoke marshalling union value-type reference-type

下面的代码是本机win32代码的笨拙。 但我收到一条错误消息

类型加载异常,无法从程序集加载,因为它包含偏移0处的对象字段,该字段未正确对齐或由非对象字段重叠

有一个带有value-type成员和reference-type的结构S1 ..这个结构是union的成员,必须有fieldOffset,但是所有S1成员都不能从fieldOffset 0开始它们是一个参考和价值类型的混合......我该如何处理?

[StructLayout(LayoutKind.Sequential)]
     public struct S1  
     {      
         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Const.FieldSizeMsgid + 1)]//Reference Type
         public String MsgId;

         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Const.FieldSizeTime + 1)]//Reference Type
         public String SendTime;

         public UInt32 SubsSeq;//Value Type
         public UInt32 ServTime;//Value Type

         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Const.FieldSizeFillerA1 + 1)]//Reference Type
         public String Filler;    
    }

     [StructLayout(LayoutKind.Explicit)]
     public struct AdminData
     {
         [FieldOffset(0)] public S1 S11;// get an error because the S1 has both reference type member and value type member

         [FieldOffset(0)] public S2 S22;

         [FieldOffset(0)] public S3 S33;
     }

我知道我必须将S1分解为2个结构,一个是值类型成员,另一个是引用类型成员..但我不知道如何做,以及如何在AdminData中引用它们,这是一个联合。

修改

这是c ++代码

typedef struct S1  
 {      
     char MsgId [Const.FieldSizeMsgid + 1];//Reference Type
     char SendTime[Const.FieldSizeTime + 1];//Reference Type
     int SubsSeq;//Value Type
     int ServTime;//Value Type
     char Filler[Const.FieldSizeFillerA1 + 1];//Reference Type  
 }
 union AdminData
 {
     S1 S11;//has both value type member and reference type member
     S2 S22;//has both value type member and reference type member
     S3 S33;//has both value type member and reference type member
 }
typedef struct MMTPMsg
{
    int Length;
    short Type;
    AdminData Data; //the union
    long long TimeStamp; 
}

1 个答案:

答案 0 :(得分:1)

正如您所发现的,您无法在值类型之上覆盖引用类型。因此,要实现您的联合,您需要使用其中一个或另一个。您的结构必须包含值类型,因此我们得出结论,您必须专门使用值类型。

那么,如何将字符数组实现为值类型?使用fixed size buffer

unsafe public struct S1  
{      
    fixed byte MsgId[Const.FieldSizeTime + 1];
    ....
}