David Brown
David Brown

Reputation: 36279

How can C++/CLI make this situation easier?

I have a little piece of a library that I would like to write a .NET wrapper for. At the moment, I'm using P/Invoke, but since I don't have the library's source code or a whole lot of C knowledge, I'm having a difficult time with marshaling. It works so far (sort of), but it feels like a hack.

C Signatures

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);

Essentially, what this does is takes the SMS_MSG_DATA struct and outputs it to a binary format in the msg_buf byte array. The initial value of msg_buf_len is the size of the byte array, but when the encoding completes, it is set to the number of bytes actually filled.

How can a C++/CLI wrapper make this process any easier and cleaner?

Upvotes: 0

Views: 367

Answers (2)

Ana Betts
Ana Betts

Reputation: 74702

This is perfectly reasonable P/Invoke code, though you should make sure that you are not passing Unicode around (check your struct defn.), because all your native declarations seem to take ANSI strings.

C++/CLI doesn't really help you too much here - the place where it makes your life easier is when you want to write some blocks of native code, and make the interface to the C# part simpler. The only thing you could do here, is if on the C# side you really only cared about 1-2 params, you could have the C++/CLI DLL fill out the rest for you and not worry about as much ugly code on the C# side

Upvotes: 1

JaredPar
JaredPar

Reputation: 755587

C++/CLI can make this easier because you don't have to write a PInvoke definition. Instead you can just use the original native SMS_MSG_DATA structure directly. You are free to write a better looking wrapper structure which is internally converted to SMS_MSG_DATA. This wrapper structure need not have any ugly PInvoke declaration and can be much more in lines with managed guidelines.

Upvotes: 0

Related Questions