C#中的联合编组问题

时间:2010-05-19 15:17:20

标签: c# marshalling

我有结构内部结构,结构看起来像

struct tDeviceProperty {

    DWORD Tag;
    DWORD Size;     
    union _DP value;    
};

typedef union _DP
{
      short int           i;       
      LONG                l;      
      ULONG               ul;     
      float               flt;    
      double              dbl;    
      BOOL      b;        
      double              at;     
      FILETIME            ft;     
      LPSTR               lpszA;  
      LPWSTR              lpszW;  
      LARGE_INTEGER       li;     
      struct tBinary    bin;    
      BYTE                reserved[40]; 
} __UDP;


struct tBinary {
    ULONG size;     
    BYTE * bin;     
};
来自tBinary结构bin的

必须转换为tImage(结构如下)

struct tImage {
    DWORD x;
    DWORD y;
    DWORD z;
    DWORD Resolution;
    DWORD type;
    DWORD ID;
    diccid_t SourceID;
    const void *buffer;
    const char *Info;
    const char *UserImageID;
}; 

在c#中使用相同的东西我已经完成了编组,但在将指针转换为结构时没有给出正确的值。 C#代码如下,

tBinary tBin = new tBinary();
IntPtr tBinbuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tBin));
Marshal.StructureToPtr(tBin.bin, tBinbuffer, false);


tDeviceProperty tDevice = new tDeviceProperty();
tDevice.bin = tBinbuffer;
IntPtr tDevicebuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tDevice));
Marshal.StructureToPtr(tDevice.bin, tDevicebuffer, false);

Battary tbatt = new Battary();
tbatt.value = tDevicebuffer;
IntPtr tbattbuffer = Marshal.AllocCoTaskMem(Marshal.SizeOf(tbatt));
Marshal.StructureToPtr(tbatt.value, tbattbuffer, false);

result = GetDeviceProperty(ref tbattbuffer);

Battary v = (Battary)Marshal.PtrToStructure(tbattbuffer, typeof(Battary));

tDeviceProperty v2 = (tDeviceProperty)Marshal.PtrToStructure(tDevicebuffer, typeof(tDeviceProperty));

tBinary v3 = (tBinary)Marshal.PtrToStructure(tBinbuffer, typeof(tBinary));






[StructLayout(LayoutKind.Explicit)]
public struct tDeviceProperty
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.U2)]
    public ushort i;
    [FieldOffset(2)]
    [MarshalAs(UnmanagedType.I4)]
    public int l;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.U4)]
    public uint ul;
    [FieldOffset(10)]
    [MarshalAs(UnmanagedType.R4)]
    public float flt;
    [FieldOffset(14)]
    [MarshalAs(UnmanagedType.R8)]
    public double dbl;
    [FieldOffset(22)]
    [MarshalAs(UnmanagedType.I4)]
    public int b;
    [FieldOffset(26)]
    [MarshalAs(UnmanagedType.R8)]
    public double at;
    [FieldOffset(34)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr ft;
    [FieldOffset(42)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr lpszA;
    [FieldOffset(43)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr lpszW;
    [FieldOffset(45)]
    [MarshalAs(UnmanagedType.U8)]
    public ulong li;
    [FieldOffset(53)]
    [MarshalAs(UnmanagedType.Struct)]
    public IntPtr bin;
    [FieldOffset(61)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr reserved;
}


[StructLayout(LayoutKind.Sequential)]
public struct tBinary
{
    public int size;
    public IntPtr bin;
}

[StructLayout(LayoutKind.Sequential)]
public struct Battary
{
    public uint Tag;
    public uint Size;
    public IntPtr value;
}

[StructLayout(LayoutKind.Sequential)]
public struct tDiccBatteryStatus
{
    public uint RefreshWear;
    public uint TotalWear;
    public ushort Voltage;
    public ushort Battery;
    public int BatteryOK;
    public int NeedRefresh;
    public int NeedChange;
    public ushort Temperature;
    public int Charge;
    public byte State;
    public byte ExternalPowered;
    public int CapacityLeft;
}

1 个答案:

答案 0 :(得分:0)

我认为失败的原因是tDeviceProperty声明。事实上,它的成员value是一个联合,但是在tDeviceProperty中你应用constatly增加偏移量,而它们应该具有相同的值。

这是因为联盟成员从相同的偏移开始,共享其他成员的相同空间。 union的大小由union中声明的字段的最大大小决定。

确实,使用您的代码:

[StructLayout(LayoutKind.Explicit, Size = )]
public struct tDeviceProperty
{
    [FieldOffset(0)]
    [MarshalAs(UnmanagedType.U2)]
    public ushort i;
    [FieldOffset(2)]
    [MarshalAs(UnmanagedType.I4)]
    public int l;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.U4)]
    public uint ul;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.R4)]
    public float flt;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.R8)]
    public double dbl;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.I4)]
    public int b;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.R8)]
    public double at;
    [FieldOffset(6)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr ft;
    [FieldOffset(6)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr lpszA;
    [FieldOffset(6)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr lpszW;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.U8)]
    public ulong li;
    [FieldOffset(6)]
    [MarshalAs(UnmanagedType.Struct)]
    public IntPtr bin;
    [FieldOffset(6)]
    //[MarshalAs(UnmanagedType.Struct)]
    public IntPtr reserved;
}

另请查看我最近的question/answer