2016-09-20 1 views
2

Ich versuche, eine C# -Schnittstelle zu erstellen, die einen Rückruf von einer externen C DLL empfängt. Die Callback-Parameter enthalten Zeiger auf C-Strukturen, die selbst einen Zeiger auf eine andere Struktur haben.C zu C# PInvoke mit Strukturen mit Zeigern

Die Callback-Signatur:

typedef application_event_result (*application_event_ptr)(abuffertype* read_buffer, abuffertype* write_buffer); 

Die Puffer struct Definitionen in C:

typedef struct { 
    uint16 size; 
    uint8* data; 
} anotherbuffertype; 

typedef struct { 
    anotherbuffertype *buffer; 
    uint16 position; 
} abuffertype; 

Ich weiß, dass das C# -Signatur des Callback "ref" für den Zeigertyp des Parameters verwenden sollte . Aber wie kann der Zeiger innerhalb der Struktur "abuffertype" in C# definiert werden?

Bisher habe ich diese Definition der beiden Strukturen in C#:

[StructLayout(LayoutKind.Sequential)] 
    public struct anotherbuffer 
    { 
     UInt16 size; 
     IntPtr data; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    public struct abuffer 
    { 
     anotherbuffer buffer; 
     UInt16 position; 
    } 

Aber das funktioniert nicht. Der Inhalt von "abuffer" in C# ist nicht das, was vor dem Callback im C-Code vorlag.

Muss ich den internen Strukturzeiger manuell entpacken, und wenn ja, wie?

Antwort

2

Sie erhalten keine Hilfe vom Marshaller, dies führt normalerweise zu einem größeren Speicherverwaltungsproblem. Kann aber im konkreten Fall eines Callbacks arbeiten, da es das aufrufende C-Programm ist, das die Daten verwaltet.

Sie müssen die Daten selbst konvertieren. Deklarieren Sie die Zeiger als IntPtr, und verwenden Sie Marshal.PtrToStructure(), um die Daten abzurufen.

Das Element anotherbuffertype.data sieht wie ein Array aus. Verwenden Sie Marshal.Copy(), um seinen Inhalt in Ihr eigenes Array byte [] zu kopieren. Wenn Sie nichts gegen das Schlüsselwort unsafe haben, können Sie es als Byte * deklarieren und auf die Elemente mit den Daten [index] zugreifen, wodurch die Kosten der Kopie vermieden werden. Es ist nicht sehr unsicher, ziemlich einfach, den Index auf [0..size] beschränkt zu halten.