2012-04-13 14 views
1

Ich rufe eine externe C-Bibliothek von einem C# -Wrapper, den ich schreibe. Eine der Funktionen, die ich anrufe, ist das Registrieren einer Rückruffunktion. Ich bekomme keine Fehler, wenn ich die setCallback Funktion aufruft, aber wenn die Callback-Funktion später aufgerufen wird, erhalte ich Fehler, leider nicht spezifiziert von der C-Bibliothek.Verwenden einer Rückruffunktion mit Parametern bei der Verwendung von P/Invoke

Hier ist der C-Methode (aus der Header-Datei)

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

meine C# Deklaration der Methode

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

meine Delegierten

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

I Diese werden hier Dies ist, wie Rufen Sie die Methode

0 auf

Hier ist die Struktur, die

von einem der Rückrufe verwendet wird
[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 Header für Callback-Funktionen wie folgt ..

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

Können Sie auch Signatur aus c-Header für connectionLost, messageArrived, deliveryComplete? – Nikolay

+0

Hallo Nikolay, ich habe diese jetzt hinzugefügt. –

Antwort

1

I/nicht viel Erfahrung mit p Rufen Sie auf, aber es sieht so aus, als ob Sie die Unterschriften der Delegierten korrigieren sollten, um sie zurückzugeben, da sie in c ungültig sind. Und auch Ref für Zeiger Parameter wie Kontext und Nachricht verwenden

+0

Vielen Dank für die Heads-up auf die Delegate Signatur Rückgabetypen, die nicht geholfen haben. Ich brauche kein 'ref' für die Parameter, da sie vom Typ 'IntPtr' sind und eine Klasse, die sowieso als Referenz verwendet wird. –

+0

Es ist IntPtr für Kontext, aber nicht für Nachricht. Ich denke, es sollte 'private delegate int MessageArrivedDelegate (IntPtr Kontext, ..., ref MessageObject Nachricht);' – Nikolay

+0

Wenn 'MessageObject' eine Struktur und nicht eine Klasse wäre ich mit Ihnen einverstanden. Ich habe es mit einem Präfix "ref" versucht und es funktioniert immer noch nicht. –

Verwandte Themen