使用P / Invoke时使用带参数的回调函数

时间:2012-04-13 10:54:53

标签: c# .net pinvoke

我正在编写一个来自我正在编写的C#包装器的外部C库。我正在调用的函数之一是注册回调函数。当我调用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);

这是其中一个回调

使用的结构
[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);

1 个答案:

答案 0 :(得分:1)

我没有很多p / invoke的经验,但看起来你应该纠正委托的签名以返回void,因为它在c中是无效的。并且还使用ref作为指针参数,如上下文和消息