C ++ / CLI如何使这种情况更容易?

时间:2009-12-09 16:32:03

标签: c# c++-cli pinvoke wrapper

我有一个库,我想为它编写一个.NET包装器。目前,我正在使用P / Invoke,但由于我没有库的源代码或大量的C知识,因此我在编组方面遇到了困难。它到目前为止(有点),但感觉就像一个黑客。

C签名

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 / Invoke

[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包装器如何使这个过程更容易和更清洁?

2 个答案:

答案 0 :(得分:1)

这是完全合理的P / Invoke代码,尽管你应该确保你传递Unicode(检查你的结构定义。),因为你的所有本机声明似乎都采用ANSI字符串。

C ++ / CLI在这里并没有真正帮助你 - 它让你的生活更轻松的地方是当你想要编写一些本机代码块,并使C#部分的接口更简单。你在这里唯一可以做的就是如果在C#方面你真的只关心1-2个参数,你可以让C ++ / CLI DLL为你填写其余部分而不用担心C#端的丑陋代码

答案 1 :(得分:0)

C ++ / CLI可以使这更容易,因为您不必编写PInvoke定义。相反,您可以直接使用原始的本地SMS_MSG_DATA结构。您可以自由编写一个更好看的包装器结构,该结构在内部转换为SMS_MSG_DATA。这个包装器结构不需要任何丑陋的PInvoke声明,并且可以更加符合托管指南。