首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > VC >

200分c#模拟c++中的联合

2012-12-15 
200分求助:c#模拟c++中的联合有关.net的P/Invoke操作也算了解,但说不上太深,基本的函数调用还可以,但对于

200分求助:c#模拟c++中的联合
有关.net的P/Invoke操作也算了解,但说不上太深,基本的函数调用还可以,但对于一些复杂的数据结构,如上面代码中的联合(union)就无法把其转换为C#以使用的结构。
注:已经看过《如何在C#中模拟C++的联合(Union)》
    http://www.cnblogs.com/allenlooplee/archive/2004/12/25/81917.html

此联合是Windows CE中调用RIL接口接收短信时,短信的数据结构
代码如下,也可以参考MSDN,更清楚:
MSDN:http://msdn.microsoft.com/en-us/library/aa919458.aspx

代码:


typedef struct {
  DWORD cbSize;
  DWORD dwParams;
  RILADDRESS raSvcCtrAddress;
  DWORD dwType;
  DWORD dwFlags;
  UNION {
    struct {
            RILADDRESS raOrigAddress;
            DWORD dwProtocolID;
            RILMSGDCS rmdDataCoding;
            SYSTEMTIME stSCReceiveTime;
            DWORD cbHdrLength;
            DWORD cchMsgLength;
            BYTE rgbHdr[MAXLENGTH_HDR];
            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgInDeliver;
    struct {
            DWORD dwTgtMsgReference;
            RILADDRESS raTgtRecipAddress;
            SYSTEMTIME stTgtSCReceiveTime;
            SYSTEMTIME stTgtDischargeTime;
            DWORD dwTgtDlvStatus;
            DWORD dwProtocolID;
            RILMSGDCS rmdDataCoding;
            DWORD cbHdrLength;
            DWORD cchMsgLength;
            BYTE rgbHdr[MAXLENGTH_HDR];
            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgInStatus;
    struct {
            RILADDRESS raDestAddress;
            DWORD dwProtocolID;
            RILMSGDCS rmdDataCoding;
            DWORD dwVPFormat;
            SYSTEMTIME stVP;
            DWORD cbHdrLength;
            DWORD cchMsgLength;
            BYTE rgbHdr[MAXLENGTH_HDR];
            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgOutSubmit;


    struct {
            DWORD dwProtocolID;
            DWORD dwCommandType;
            DWORD dwTgtMsgReference;
            RILADDRESS raDestAddress;
            DWORD cbCmdLength;
            BYTE rgbCmd[MAXLENGTH_CMD];
           } msgOutCommand;
    struct {
            DWORD dwGeoScope;
            DWORD dwMsgCode;
            DWORD dwUpdateNumber;
            DWORD dwID;
            RILMSGDCS rmdDataCoding;
            DWORD dwTotalPages;
            DWORD dwPageNumber;
            DWORD cchMsgLength;
            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgBcGeneral;
    struct {
            DWORD cchMsgLength;
            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgOutRaw;
    struct {
            RILADDRESS raOrigAddress;
            RILSUBADDRESS rsaOrigSubaddr;
            SYSTEMTIME stSCReceiveTime;
            SYSTEMTIME stValidityPeriodAbs;
            SYSTEMTIME stValidityPeriodRel;
            SYSTEMTIME stDeferredDelTimeAbs;
            SYSTEMTIME stDeferredDelTimeRel;
            DWORD dwNumMsgs;
            RILADDRESS raCallBackNumber; 
            DWORD dwMsgPriority; 
            DWORD dwMsgPrivacy;
            BOOL bUserAckRequest; 
            DWORD dwMsgDisplayMode;
            DWORD dwTeleservice; 
            DWORD dwMsgID;
            DWORD dwMsgLang;
            DWORD dwMsgEncoding;
            DWORD cchMsgLength;


            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgIS637InDeliver;
    struct {
            RILADDRESS raDestAddress;
            RILSUBADDRESS rsaDestSubaddr;
            BOOL bDigit;
            SYSTEMTIME stValidityPeriodAbs;
            SYSTEMTIME stValidityPeriodRel;
            SYSTEMTIME stDeferredDelTimeAbs;
            SYSTEMTIME stDeferredDelTimeRel;
            BOOL bDeliveryAckRequest;
            BOOL bUserAckRequest;
            BOOL bBearerReplyRequest;
            DWORD dwReplySeqNumber;
            DWORD dwMsgDisplayMode;
            RILADDRESS raCallBackNumber;
            DWORD dwMsgPriority;
            DWORD dwMsgPrivacy;
            DWORD dwTeleservice;
            DWORD dwMsgID;
            DWORD dwMsgLang;
            DWORD dwMsgEncoding; 
            DWORD cchMsgLength;  
            BYTE rgbMsg[MAXLENGTH_MSG]; 
           } msgIS637OutSubmit;
    struct { 
            RILADDRESS raOrigAddress;
            RILSUBADDRESS rsaOrigSubaddr;
            SYSTEMTIME stSCReceiveTime;
            DWORD dwCauseCode;
            DWORD dwReplySeqNumber;
            DWORD dwUserResponseCode;
            DWORD dwMsgStatusType;
            DWORD dwMsgID;
            DWORD dwMsgLang;
            DWORD dwMsgEncoding;
            DWORD cchMsgLength;
            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgIS637InStatus;
    struct {
            RILADDRESS raDestAddress;


            RILSUBADDRESS rsaDestSubaddr;
            BOOL bDigit;
            DWORD dwReplySeqNumber;
            DWORD dwUserResponseCode;
            DWORD dwMsgID;
            DWORD dwMsgLang;
            DWORD dwMsgEncoding;
            DWORD cchMsgLength;
            BYTE rgbMsg[MAXLENGTH_MSG];
           } msgIS637OutStatus;
        }
} RILMESSAGE;



结构中使用到的其它结构,MSDN中都有,可以参考
http://msdn.microsoft.com/en-us/library/aa919130(v=MSDN.10).aspx

我自己写的C#的封装,但运行出错。
代码:

        #region RILMESSAGE struct

        private struct RILMESSAGE
        {
            public UInt32 cbSize;
            public UInt32 dwParams;    
            public RILADDRESS raSvcCtrAddress;
            public UInt32 dwType;
            public UInt32 dwFlags;
            public UNION Msg;
        }

        [StructLayout(LayoutKind.Explicit)]
        private struct UNION
        {
            [FieldOffset(0)]
            public msgInDeliver _msgInDeliver;
            [FieldOffset(0)]
            public msgInStatus _msgInStatus;
            [FieldOffset(0)]
            public msgOutSubmit _msgOutSubmit;
            [FieldOffset(0)]
            public msgOutCommand _msgOutCommand;
            [FieldOffset(0)]
            public msgBcGeneral _msgBcGeneral;
            [FieldOffset(0)]
            public msgOutRaw _msgOutRaw;

        }

        #region 用于UNION中的Struct

        [StructLayout(LayoutKind.Sequential)]


        private struct msgInDeliver
        {
            public RILADDRESS raOrigAddress;
            public UInt32 dwProtocolID;
            public RILMSGDCS rmdDataCoding;
            public SYSTEMTIME stSCReceiveTime;
            public UInt32 cbHdrLength;
            public UInt32 cchMsgLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] rgbHdr;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] rgbMsg;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct msgInStatus
        {
            public UInt32 dwTgtMsgReference;
            public RILADDRESS raTgtRecipAddress;
            public SYSTEMTIME stTgtSCReceiveTime;
            public SYSTEMTIME stTgtDischargeTime;
            public UInt32 dwTgtDlvStatus;
            public UInt32 dwProtocolID;
            public RILMSGDCS rmdDataCoding;
            public UInt32 cbHdrLength;
            public UInt32 cchMsgLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] rgbHdr;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] rgbMsg;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct msgOutSubmit
        {
            public RILADDRESS raDestAddress;
            public UInt32 dwProtocolID;
            public RILMSGDCS rmdDataCoding;
            public UInt32 dwVPFormat;
            public SYSTEMTIME stVP;


            public UInt32 cbHdrLength;
            public UInt32 cchMsgLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] rgbHdr;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] rgbMsg;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct msgOutCommand
        {
            public UInt32 dwProtocolID;
            public UInt32 dwCommandType;
            public UInt32 dwTgtMsgReference;
            public RILADDRESS raDestAddress;
            public UInt32 cbCmdLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
            public byte[] rgbCmd;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct msgOutRaw
        {
            public UInt32 cchMsgLength;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] rgbMsg;
        }

        #endregion

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
        private struct RILADDRESS
        {
            public UInt32 cbSize;
            public UInt32 dwParams;      
            public UInt32 dwType;
            public UInt32 dwNumPlan;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public StringBuilder wszAddress; 
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RILMSGDCS
        {
            public UInt32 cbSize;


            public UInt32 dwParams;     
            public UInt32 dwType;
            public UInt32 dwFlags;
            public UInt32 dwMsgClass;
            public UInt32 dwAlphabet;
            public UInt32 dwIndication;
            public UInt32 dwLanguage;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct SYSTEMTIME
        {
            public short wYear;
            public short wMonth;
            public short wDayOfWeek;
            public short wDay;
            public short wHour;
            public short wMinute;
            public short wSecond;
            public short wMilliseconds;
        }

        #endregion



有对C#互操作有经验的前辈给于指点,如能帮助实现,不胜感激。
[解决办法]

帮顶...
[解决办法]
顶个   SF
[解决办法]
主要是结构中有联合,联合中有又有结构
[解决办法]
问题已经解决,经过查找资料,联合可以说是对一块内存的操作,反映到C#中,可以用byte[]来映射这块内存。
下面的代码是实现:

    #region RILMESSAGE struct

    public struct RILMESSAGE
    {
        public UInt32 cbSize;
        public UInt32 dwParams;
        [MarshalAs(UnmanagedType.Struct, SizeConst = 528)]
        public RILADDRESS raSvcCtrAddress;
        public UInt32 dwType;
        public UInt32 dwFlags;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1356)] //最大的结构为2212。短信结构长度为1356
        public byte[] Msg;
    }

    #region 用于UNION中的10个Struct

    [StructLayout(LayoutKind.Sequential)]
    public struct msgInDeliver
    {
        public RILADDRESS raOrigAddress;
        public UInt32 dwProtocolID;


        public RILMSGDCS rmdDataCoding;
        public SYSTEMTIME stSCReceiveTime;
        public UInt32 cbHdrLength;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
        public byte[] rgbHdr;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgInStatus
    {
        public UInt32 dwTgtMsgReference;
        public RILADDRESS raTgtRecipAddress;
        public SYSTEMTIME stTgtSCReceiveTime;
        public SYSTEMTIME stTgtDischargeTime;
        public UInt32 dwTgtDlvStatus;
        public UInt32 dwProtocolID;
        public RILMSGDCS rmdDataCoding;
        public UInt32 cbHdrLength;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
        public byte[] rgbHdr;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgOutSubmit
    {
        public RILADDRESS raDestAddress;
        public UInt32 dwProtocolID;
        public RILMSGDCS rmdDataCoding;
        public UInt32 dwVPFormat;
        public SYSTEMTIME stVP;
        public UInt32 cbHdrLength;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
        public byte[] rgbHdr;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgOutCommand
    {
        public UInt32 dwProtocolID;
        public UInt32 dwCommandType;
        public UInt32 dwTgtMsgReference;
        public RILADDRESS raDestAddress;


        public UInt32 cbCmdLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
        public byte[] rgbCmd;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgBcGeneral
    {
        public UInt32 dwGeoScope;
        public UInt32 dwMsgCode;
        public UInt32 dwUpdateNumber;
        public UInt32 dwID;
        public RILMSGDCS rmdDataCoding;
        public UInt32 dwTotalPages;
        public UInt32 dwPageNumber;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgOutRaw
    {
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgIS637InDeliver
    {
        public RILADDRESS raOrigAddress;
        public RILSUBADDRESS rsaOrigSubaddr;
        public SYSTEMTIME stSCReceiveTime;
        public SYSTEMTIME stValidityPeriodAbs;
        public SYSTEMTIME stValidityPeriodRel;
        public SYSTEMTIME stDeferredDelTimeAbs;
        public SYSTEMTIME stDeferredDelTimeRel;
        public UInt32 dwNumMsgs;
        public RILADDRESS raCallBackNumber;
        public UInt32 dwMsgPriority;
        public UInt32 dwMsgPrivacy;
        public bool bUserAckRequest;
        public UInt32 dwMsgDisplayMode;
        public UInt32 dwTeleservice;
        public UInt32 dwMsgID;
        public UInt32 dwMsgLang;
        public UInt32 dwMsgEncoding;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;


    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgIS637OutSubmit
    {
        public RILADDRESS raDestAddress;
        public RILSUBADDRESS rsaDestSubaddr;
        private bool bDigit;
        public SYSTEMTIME stValidityPeriodAbs;
        public SYSTEMTIME stValidityPeriodRel;
        public SYSTEMTIME stDeferredDelTimeAbs;
        public SYSTEMTIME stDeferredDelTimeRel;
        private bool bDeliveryAckRequest;
        private bool bUserAckRequest;
        private bool bBearerReplyRequest;
        public UInt32 dwReplySeqNumber;
        public UInt32 dwMsgDisplayMode;
        public RILADDRESS raCallBackNumber;
        public UInt32 dwMsgPriority;
        public UInt32 dwMsgPrivacy;
        public UInt32 dwTeleservice;
        public UInt32 dwMsgID;
        public UInt32 dwMsgLang;
        public UInt32 dwMsgEncoding;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgIS637InStatus
    {
        public RILADDRESS raOrigAddress;
        public RILSUBADDRESS rsaOrigSubaddr;
        public SYSTEMTIME stSCReceiveTime;
        public UInt32 dwCauseCode;
        public UInt32 dwReplySeqNumber;
        public UInt32 dwUserResponseCode;
        public UInt32 dwMsgStatusType;
        public UInt32 dwMsgID;
        public UInt32 dwMsgLang;
        public UInt32 dwMsgEncoding;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct msgIS637OutStatus
    {
        public RILADDRESS raDestAddress;


        public RILSUBADDRESS rsaDestSubaddr;
        public bool bDigit;
        public UInt32 dwReplySeqNumber;
        public UInt32 dwUserResponseCode;        
        public UInt32 dwMsgID;
        public UInt32 dwMsgLang;
        public UInt32 dwMsgEncoding;
        public UInt32 cchMsgLength;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
        public byte[] rgbMsg;
    }

    #endregion

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct RILSUBADDRESS
    {
        public UInt32 cbSize;
        public UInt32 dwParams;
        public UInt32 dwType;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string wszSubAddress;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct RILMSGDCS
    {
        public UInt32 cbSize;
        public UInt32 dwParams;
        public UInt32 dwType;
        public UInt32 dwFlags;
        public UInt32 dwMsgClass;
        public UInt32 dwAlphabet;
        public UInt32 dwIndication;
        public UInt32 dwLanguage;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SYSTEMTIME
    {
        public ushort wYear;
        public ushort wMonth;
        public ushort wDayOfWeek;
        public ushort wDay;
        public ushort wHour;
        public ushort wMinute;
        public ushort wSecond;
        public ushort wMilliseconds;

        public override string ToString()
        {
            return wYear.ToString() + "-" + wMonth.ToString() + "-" + wDay.ToString() + " "
                   + wHour.ToString() + ":" + wMinute.ToString() + ":" + wSecond.ToString();


        }
    }

    #endregion


具体调用的时候,因为同一时间联合中只有一个结构,而且可以根据dwType来确认是使用的哪一个结构,这时可以使用如下的方法,把byte[]转换成相应的结构:
lpData是IntPtr类型

RILMESSAGE msg = (RILMESSAGE) Marshal.PtrToStructure(lpData, typeof (RILMESSAGE));

以上取出了RILMESSAGE

        msgInDeliver msgIn = (msgInDeliver)Ril.BytesToStruct(msg.Msg, typeof(msgInDeliver));

        public static object BytesToStruct(byte[] bytes, Type type)
        {
            //得到结构的大小
            int size = Marshal.SizeOf(type);

            //byte数组长度小于结构的大小
            if (size > bytes.Length)
            {
                //返回空
                return null;
            }
            //分配结构大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将byte数组拷到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回结构
            return obj;
        }

以上把byte[]类型的msg.Msg转换为结构msgInDeliver。msg.Msg也就是联合指向的内存中的数据

[解决办法]
在此感谢各位同行的回复。

备注:在解决这个问题的过程中,收集的相关资料:
RilNET    一个老外写的调用RIL接口.net实现,但并不包括本贴提到的RILMESSAGE结构
http://rilnet.codeplex.com/

RIL MSDN
http://msdn.microsoft.com/en-us/library/aa919130(v=MSDN.10).aspx

如何在C#中模拟C++的联合(Union)?[C#, C++]
http://www.cnblogs.com/allenlooplee/archive/2004/12/25/81917.html

C#中struct的内存对齐
http://qingchina.bokee.com/3399821.html

Mastering structs in C#
http://www.vsj.co.uk/articles/display.asp?id=501
[解决办法]
lpData  这个指针 在哪里定义的。。

热点排行