Wie kann ich diese c-Funktion in c # (unmarshalling return struct) aufrufen?

8

Ich möchte c # interop verwenden, um eine Funktion aus einer in c geschriebenen DLL aufzurufen. Ich habe die Header-Dateien. Sieh dir das an:

%Vor%

Wie rufe ich ctm_begin_customer_transaction von c # auf. Die const char * mapps gut zu bespannen, aber trotz verschiedenen Versuche (bei Stackoverflow und anderen Seiten suchen), habe ich nicht die Rückkehr Struktur Marschall. Wenn ich die Funktion zum Zurückgeben von IntPtr definiere, funktioniert es ok ...

Bearbeiten Ich habe den Rückgabetyp in IntPtr geändert und verwende:     CTMBeginTransactionResult structure = (CTMBeginTransactionResult) Marshal.PtrToStructure (PTR, typeof (CTMBeginTransactionResult)); aber es löst AccessViolationException

aus

Ich habe es auch versucht:

%Vor%

String == "70e3589b-2de0-4d1e-978d-55e22225be95 \ 0 \" \ 0 \ 0 \ a \ 0 \ 0 \ b \ b? "An dieser Stelle. Die" 70e3589b-2de0-4d1e-978d- 55e22225be95" ist die szTransactionID von der Struktur. Wo die Enum ist? ist es das nächste Byte?

    
Eiver 08.03.2013, 12:03
quelle

2 Antworten

1

Ich hasse es, meine eigene Frage zu beantworten, aber ich fand die Lösung, um die resultierende Struktur zu marshallen. Die Struktur ist 8 Byte lang (4 Byte für das Zeichen * und 4 Byte für die Enumeration). Das Marshalling der Zeichenfolge funktioniert nicht automatisch, aber Folgendes funktioniert:

%Vor%

Der Code funktioniert, aber ich muss noch untersuchen, ob der Aufruf des nicht verwalteten Codes Speicherlecks zur Folge hat.

    
Eiver 11.03.2013, 13:37
quelle
5

In dieser Struktur ist ein Speicherverwaltungsproblem verborgen. Wem gehört der C-String-Zeiger? Der pinvoke Marshaller wird immer annehmen, dass der Anrufer ihn besitzt, so dass er versuchen wird, die Zeichenfolge freizugeben. Und übergibt den Zeiger auf CoTaskMemFree (), dieselbe Funktion wie die von Marshal.FreeCoTaskMem genannt (). Diese Funktionen verwenden den COM-Speicherzuordner, den universellen Interop-Speichermanager in Windows.

Dies kommt selten zu einem guten Ende, C-Code verwendet diesen Zuordner normalerweise nicht, es sei denn, der Programmierer hat seinen Code unter Berücksichtigung von Interop entworfen. In diesem Fall hat er noch nie eine Struktur als Rückgabewert, Interop funktioniert immer viel weniger störungsfrei, wenn der Anrufer liefert Puffer.

verwendet

Sie können es sich also nicht leisten, dass der Marshall seine normale Aufgabe erfüllt. Sie müssen den Rückgabewerttyp als IntPtr deklarieren, damit er die Zeichenfolge nicht freigibt. Und Sie müssen es selbst mit Marshal.PtrToStructure (). Marshal.PtrToStructure ().

Das lässt aber immer noch die Frage unbeantwortet, wem gehört die Zeichenfolge? Sie können nichts tun, um den Zeichenfolgenpuffer freizugeben, Sie haben keinen Zugriff auf den im C-Code verwendeten Zuordner. Die einzige Hoffnung, die Sie haben, ist, dass die Zeichenfolge nicht wirklich auf dem Heap zugewiesen wurde. Das ist möglich, das C-Programm verwendet String-Literale. Sie müssen diese Schätzung überprüfen. Rufen Sie die Funktion in einem Testprogramm eine Milliarde Mal auf. Wenn das Programm nicht explodiert, dann bist du gut. Wenn nicht, dann kann nur C ++ / CLI dein Problem lösen. Angesichts der Art der Zeichenfolge, eine "Transaktions-ID" sollte sich sehr ändern, ich würde sagen, Sie haben ein Problem.

    
Hans Passant 08.03.2013 13:18
quelle

Tags und Links