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 を渡していないことを確認する必要があります (構造体の定義を確認してください)。すべてのネイティブ宣言が ANSI 文字列を使用しているように見えるためです。

C++/CLI は、ここではあまり役に立ちません。ネイティブ コードのブロックをいくつか記述し、C# 部分へのインターフェイスをよりシンプルにしたい場合に、C++/CLI が役立つのです。ここでできる唯一のことは、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 に答える