你认识我吗?我认识他吗?他认识你吗?

比美军还厉害的就是美色,和美色一样厉害的就是美元...
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

c#模拟c++中的复杂联合问题

Posted on 2010-04-19 17:50  [David.S]  阅读(568)  评论(5编辑  收藏  举报

有关.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;                       // @field structure size in bytes 
            public UInt32 dwParams;                     // @field indicates valid parameters           
            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中的10个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 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)]
        
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;                       // @field structure size in bytes 
            public UInt32 dwParams;                     // @field indicates valid parameters           
            public UInt32 dwType;
            
public UInt32 dwNumPlan;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst 
= 256)]
            
public StringBuilder wszAddress; 
        }

        [StructLayout(LayoutKind.Sequential, CharSet 
= CharSet.Unicode)]
        
private struct RILSUBADDRESS
        {
            
public UInt32 cbSize;                       // @field structure size in bytes 
            public UInt32 dwParams;                     // @field indicates valid parameters           
            public UInt32 dwType;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst 
= 256)]
            
public StringBuilder wszSubAddress;
        }

        [StructLayout(LayoutKind.Sequential)]
        
private struct RILMSGDCS
        {
            
public UInt32 cbSize;                       // @field structure size in bytes 
            public UInt32 dwParams;                     // @field indicates valid parameters           
            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#互操作有经验的前辈给于指点,如能帮助实现,不胜感激。

 

C#测试程序源代码:

/Files/DavidS/RILTest.rar

测试程序说明:

环境:vs2005 + Windows Mobile 5.0 SDK

功能说明:当手机收到短信时,截获短信。

当手机收到短信时,代码中的RIL类中的_NotifyCallback函数会执行,并可以用以下代码取出消息体。

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

但因为RILMESSAGE结构到c#的模拟失败,所以程序报错。