2009-12-09 22 views
0

我有一小部分庫,我想寫一個.NET包裝。目前,我正在使用P/Invoke,但由於我沒有圖書館的源代碼或大量的C知識,因此我在編組時遇到了困難。它到目前爲止(有點),但它感覺像一個黑客。C++/CLI如何使這種情況更容易?

Ç簽名

typedef struct 
{ 
    unsigned short sAddress[MAX_ADDRESS_CHAR_LENGTH + 1]; 
    unsigned short sCallback[MAX_CALLBACK_CHAR_LENGTH + 1]; 
    unsigned short sMessage[(MAX_MESSAGE_CHAR_LENGTH + 1) ]; 
    unsigned short sSmscAddress[MAX_ADDRESS_CHAR_LENGTH+1]; 
    unsigned short sSubject[MAX_SUBJECT_CHAR_LENGTH + 1]; 
    unsigned char msgLength;   
    unsigned char pduType; 
    unsigned short msgRef; 
    unsigned char msgSequence; 
    unsigned char msgTotal; 
    EMsgPriority nPriority; 
    struct tm  tTime; 
    EncodingType encoding; 
    unsigned char bReceipt; 
    unsigned long dwDataMask; 
    struct tm  tValidity; 
    unsigned char nValidityType; 
    unsigned char bRelativeValidityFlag; 
    unsigned char isDeliveryAck; 
} SMS_MSG_DATA; 

unsigned short SmsEncodeMessage(SMS_MSG_DATA* sms_msg, unsigned char* msg_buf, 
    unsigned short* msg_buf_len); 

C#P /調用

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
public struct SMS_MSG_DATA { 
    [MarshalAs(UnmanagedType.ByValTStr, 
     SizeConst=SmsEncoding.MAX_ADDRESS_CHAR_LENGTH+1)] 
    public string sAddress; 

    [MarshalAs(UnmanagedType.ByValTStr, 
     SizeConst=SmsEncoding.MAX_CALLBACK_CHAR_LENGTH+1)] 
    public string sCallback; 

    [MarshalAs(UnmanagedType.ByValTStr, 
     SizeConst=SmsEncoding.MAX_MESSAGE_CHAR_LENGTH+1)] 
    public string sMessage; 

    [MarshalAs(UnmanagedType.ByValTStr, 
     SizeConst=SmsEncoding.MAX_ADDRESS_CHAR_LENGTH+1)] 
    public string sSmscAddress; 

    [MarshalAs(UnmanagedType.ByValTStr, 
     SizeConst=SmsEncoding.MAX_SUBJECT_CHAR_LENGTH+1)] 
    public string sSubject; 

    public byte msgLength; 
    public byte pduType; 
    public ushort msgRef; 
    public byte msgSequence; 
    public byte msgTotal; 
    public EMsgPriority nPriority; 
    public tm tTime; 
    public EncodingType encoding; 
    public byte bReceipt; 
    public long dwDataMask; 
    public tm tValidity; 
    public byte nValidityType; 
    public byte bRelativeValidityFlag; 
    public byte isDeliveryAck; 
} 

[DllImport(Constants.LIB_SMSENCODE)] 
public static extern ErrorCode SmsEncodeMessage(ref SMS_MSG_DATA sms_msg, 
    byte[] msg_buf, ref short msg_buf_len); 

本質上,這樣做是需要的SMS_MSG_DATA結構並將其輸出到一個二進制格式msg_buf字節數組中。 msg_buf_len的初始值是字節數組的大小,但是當編碼完成時,它被設置爲實際填充的字節數。

C++/CLI包裝程序如何使此過程更簡單,更清潔?

+0

它可以通過刪除屬性聲明使其更清潔,但不要期望太多... – 2009-12-09 16:37:10

回答

0

C++/CLI可以使這更容易,因爲您不必編寫PInvoke定義。相反,您可以直接使用原始本機SMS_MSG_DATA結構。你可以自由地寫一個更好看的包裝結構,內部轉換爲SMS_MSG_DATA。這個包裝器結構不需要任何醜陋的PInvoke聲明,並且可以更符合管理指南。

+0

在這種情況下,我仍然必須確切知道哪些託管類型可以轉換爲非託管類型, SMS_MSG_DATA'結構,對吧?我現在遇到的問題是結構聲明不完全正確,所以數據不能正確編組,導致Encode方法阻塞某些字段。 – 2009-12-09 16:44:56

+0

@David:不同的是,在C++/CLI中你可以自己進行轉換(通過強制轉換和/或編碼器等)。 – 2009-12-09 17:00:35

1

這是完全合理的P/Invoke代碼,儘管你應該確保你是而不是傳遞Unicode(檢查你的結構定義),因爲你所有的本地聲明似乎都採用ANSI字符串。

C++/CLI在這裏並沒有太多的幫助你 - 它讓你的生活更輕鬆的地方是當你想編寫一些本地代碼塊,並且簡化C#部分的接口。你可以在這裏做的唯一事情是,如果在C#方面你真的只關心1-2個參數,你可以讓C++/CLI DLL爲你填充剩下的,而不用擔心C#端的代碼太多

+0

我最初在結構上沒有'CharSet.Unicode',但Encode方法沒有正確編碼字符串。但是,當我將其更改爲Unicode時,它運行良好。 – 2009-12-09 16:46:04

+0

CharSet.ASCII如何? – 2009-12-09 16:56:36

+0

我不明白他的本地聲明是如何採用ANSI字符串的。例如。 'unsigned short sAddress [...]' - 注意這裏的'short' - 對我來說非常像UTF-16字符串! – 2009-12-09 16:58:49