0

我有一个库的一小部分,我想为其编写一个 .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/调用

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

4

2 回答 2

1

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

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

于 2009-12-09T16:36:02.327 回答
0

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

于 2009-12-09T16:35:02.773 回答