Entwickler-Ecke

Basistechnologien - pchar Rückgabe aus Delphi-DLL


Tastaro - Di 12.09.17 11:34
Titel: pchar Rückgabe aus Delphi-DLL
Hallo,

ich habe in eine Delphi-DLL eine Funktion die so aussieht:


Delphi-Quelltext
1:
function foo(pcResultBuffer: pchar; iResultBufferSize: integer): integer; stdcall;                    

In pcResultBuffer wird ein String zurückgegeben. iResultBufferSize teilt die Größe des Buffers mit, auf den pcResultBuffer zeigt.

Diese möchte ich unter C# verwenden.
Ich importiere die DLL dynamisch. Also lege ich einen Typ an (Ist das so richtig?):


C#-Quelltext
1:
2:
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int FooCallbackType([MarshalAs(UnmanagedType.LPStr)] string resultBuffer, int resultBufferSize);


... der dann verwendet wird


C#-Quelltext
1:
private FooCallbackType fooCallback = null;                    


Das Auslesen der Funktionszeiger:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
private void GetProcAddresses()
{
    IntPtr funcAddr = IntPtr.Zero;
    
    funcAddr = GetProcAddress(dllHandle, "foo");
    if (funcAddr != IntPtr.Zero)
        fooCallback = (FooCallbackType)Marshal.GetDelegateForFunctionPointer(
            funcAddr, typeof(FooCallbackType));
}


Jetzt fehlt noch der Aufruf der Funktion. Wie mache ich das? Genauer: Wie initialisiere ich den Buffer auf eine bestimmte Länge, damit die Delphi-Funktion was hineinschreiben kann?


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
string resultBuffer;
int bufferSize;
int charsInBuffed;

//hier Buffer-Initialiserierung ????

charsInBuffed = foo(resultBuffer, bufferSize);


Oder muss man das ganz anders machen?


Th69 - Di 12.09.17 12:04

Lies dir mal Using the StringBuilder in Unmanaged API Calls [https://limbioliong.wordpress.com/2011/11/01/using-the-stringbuilder-in-unmanaged-api-calls/] durch (Lösung bei dir also entsprechend "2.4 Using StringBuilder").


Delete - Di 12.09.17 12:14

- Nachträglich durch die Entwickler-Ecke gelöscht -


Tastaro - Di 12.09.17 12:41

@Frühlingsrolle: GetProcAddress ist schon klar. Das dynamische Einbinden klappt wunderbar.
Ich binde DLLs lieber dynamisch als statisch ein, dann habe ich eine bessere Kontrolle über das Verhalten meines Programms, wenn die DLL nicht vorhanden ist. In manchen Fällen wird sie auch gar nicht benötigt.

Mir ging es hauptsächlich um die Rückgabe eines Strings in einem Buffer.

@Th69: Danke für den Link. Das werde ich mal probieren.


Delete - Di 12.09.17 14:53

- Nachträglich durch die Entwickler-Ecke gelöscht -


Tastaro - Mi 13.09.17 12:04

@Frühlingsrolle: Die Delphi-Funktion erwartet, dass der Speicher des Buffers schon reserviert ist. Mit der Variante gäbe es eine Zugriffstverletzung.

@Th69: Mit dem StringBuilder klappt es super. Danke!