C++Union结构体转换成C#代码

C++Union结构体转换成C#代码
2010年10月27日
  有关.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
  代码:
  C/C++ code 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;
  下面的代码是实现:
  C# code #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类型
  C# code RILMESSAGE msg = (RILMESSAGE) Marshal.PtrToStructure(lpData, typeof (RILMESSAGE));
  以上取出了RILMESSAGE
  C# code 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也就是联合指向的内存中的数据
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值