开发者

union marshalling issue in C#

开发者 https://www.devze.com 2022-12-30 16:55 出处:网络
I have union inside structure and the structure looks like struct tDeviceProperty { DWORD Tag; DWORD Size;

I have union inside structure and the structure looks like

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

from the tBinary structure bin has to be converted to tImage (structure is given below)

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

to use the same in c# I have done marshaling but not giving proper values when converting the pointer to structure. The C# code is follows,

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;
    开发者_Python百科[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;
}


I think that the reason of the failure is the tDeviceProperty declaration. Infact, its member value is an union, but in the tDeviceProperty you apply constatly increasing offset, while they shall have the same value.

This is because the union members start at the same offset, sharing the same space of the other members. The size of the union is determines by the maximum size of the fields declared in the union.

Indeed, using your code:

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

Check also my recent question/answer.

0

精彩评论

暂无评论...
验证码 换一张
取 消