1

私が書いている C# ラッパーから外部 C ライブラリを呼び出しています。私が呼び出している関数の 1 つは、コールバック関数を登録することです。関数を呼び出してもエラーは発生しませんsetCallbackが、コールバック関数が後で呼び出されるとエラーが発生します。残念ながら、C ライブラリでは指定されていません。

これがCメソッドです(ヘッダーファイルから)

DLLExport int setCallbacks(Client handle, void* context, connectionLost* cl,
messageArrived* ma, deliveryComplete* dc);

メソッドのC#宣言は次のとおりです

[DllImport("some.dll", CharSet = CharSet.Auto, ExactSpelling = false, 
CallingConvention = CallingConvention.Cdecl)]
private static extern int setCallbacks(IntPtr client, IntPtr context,
MulticastDelegate connectionLost, MulticastDelegate messageArrived, 
MulticastDelegate messageDelivered);

これらは私の代理人です

private delegate int ConnectionLostDelegate(IntPtr context, [MarshalAs(UnmanagedType.LPStr)] String cause);
private delegate int MessageArrivedDelegate(IntPtr context, [MarshalAs(UnmanagedType.LPStr)] String title, Int32 titleLength, MessageObject message);
private delegate int MessageDeliveredDelegate(IntPtr context, int deliveryToken);

これは私がメソッドを呼び出す方法です

ConnectionLostDelegate conLost = new ConnectionLostDelegate(ConnectionLost);
MessageArrivedDelegate mesArr = new MessageArrivedDelegate(MessageArrived);
MessageDeliveredDelegate mesDel = new MessageDeliveredDelegate(MessageDelivered);

result = setCallbacks(client, IntPtr.Zero, conLost, mesArr, mesDel);

コールバックの 1 つで使用される構造体を次に示します。

[StructLayout(LayoutKind.Sequential)]
public class MessageObject
{
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 4, ArraySubType = UnmanagedType.U1)]
    public byte[] struct_id;
    Int32 struct_version;
    Int32 payloadlen;
    IntPtr payload;
    Int32 qos;
    Int32 retained;
    Int32 dup;
    Int32 msgid;

    public MessageObject()
    {
        struct_id = Encoding.ASCII.GetBytes("WXYZ");
        struct_version = 0;
        payload = IntPtr.Zero;
    }
}

コールバック関数の C ヘッダーは次のとおりです。

typedef int messageArrived(void* context, char* title, int titleLen, MessageObject* message);

typedef void deliveryComplete(void* context, int token);

typedef void connectionLost(void* context, char* cause);
4

1 に答える 1

1

p/invoke の経験はあまりありませんが、デリゲートの署名を修正して void を返す必要があるようです。c では void です。また、コンテキストやメッセージなどのポインターパラメーターにも ref を使用します

于 2012-04-13T11:26:23.147 に答える