![]() |
String-Übergabe von Delphi-DLL an C#
Hi
Wenn ich in C# einen String aus einer Delphi-DLL haben möchte, stürzt die C#-Anwendung ab. Jetzt wurde mir gesagt, daß ich es so machen soll:
Delphi-Quellcode:
Die Funktion delphi_getString sieht so aus:
[DllImport("delphiDLL.dll")]
private static extern IntPtr delphi_getString(); ... IntPtr pStr = delphi_getString(); string str = Marshal.PtrToStringAnsi(pStr); // now pinvoke to free string if needed delphi_freeString(pStr); ...
Delphi-Quellcode:
Was mich jetzt interessiert, ist die letzte Anweisung in dem C#-Code.
function delphi_getString():PAnsiChar; cdecl; exports delphi_getString;
function delphi_getString():PAnsiChar; var text:string; Begin text:='TestString'; result:=PAnsiChar(AnsiString(text)); End; delphi_freeString(pStr); Soweit ich weiß, werden doch in Delphi lokale Variablen und Pointer automatisch aus dem Speicher entfernt, wenn die Funktion beendet ist. Auch IntPtr pStr sollte in C# nur solange gültig sein, bis auch dort die Funktion beendet ist. Oder irre ich mich hier komplett? Danke |
AW: String-Übergabe von Delphi-DLL an C#
Und wenn Du die DLL-Funktion so umschreibst, dass sie einen PAnsiChar und dessen Länge als Parameter übergeben bekommt und dann lediglich befüllt? Ich möchte bezweifeln, dass ein Zeiger auf eine lokale Stringvariable innerhalb der DLL als Funktionsrückgabe funktioniert.
|
AW: String-Übergabe von Delphi-DLL an C#
So ganz habe ich das in Delphi jetzt immer noch nicht verstanden, aber wenn die Funktion endet, dann gibt es auch keine Referenz mehr auf den String und er wird entfernt.
Delphi-Quellcode:
kopiert, laut Hilfe, den String nicht, deine Funktion gibt letztendlich eine Adresse auf etwas zurück, dass wohl direkt wieder abgeräumt wird.
PAnsiChar
Mit
Delphi-Quellcode:
scheint man explizit den String auf den Heap zu schreiben und dort zu lassen.
StrNew
Geschickter wäre es allerdings, in deinem Programm den Speicher anzulegen, die Adresse an die DLL zu schicken und den Speicher auch selbst wieder im Programm freizuräumen, dann bräuchtest du das
Delphi-Quellcode:
auch nicht.
delphi_freeString()
|
AW: String-Übergabe von Delphi-DLL an C#
Du musst in Delphi einen WideString benutzen, der passt mit den String Datentyp in C# überein.
|
AW: String-Übergabe von Delphi-DLL an C#
DeddyH hat die Methode schlechthin schon angeführt - damit kommt man als DLL überall an. Nicht umsonst verwendet die WinAPI selber genau dieselbe :)
|
AW: String-Übergabe von Delphi-DLL an C#
Ungetestet:
Delphi-Quellcode:
const
ERROR_NO_ERROR = 0; ERROR_BUFFER_TOO_SMALL = 1; function delphi_getString(Buffer: PAnsiChar; var BufSize: DWORD): DWORD; cdecl; var Test: AnsiString; begin Test := 'Hallo Welt'; if BufSize < Length(Test) then Result := ERROR_BUFFER_TOO_SMALL; else begin StrPCopy(Buffer, Test); Result := ERROR_NO_ERROR; end; BufSize := Length(Test); end; |
AW: String-Übergabe von Delphi-DLL an C#
Zitat:
Zurück zum Thema: Ergänz mal deinen Dll-Import um die Charset-Angabe ( ![]() |
AW: String-Übergabe von Delphi-DLL an C#
@DeddyH:
Der Code produziert leider einen Absturz. Ich habe jetzt einfach mal den lokalen Delphi-String zu einem globalen gemacht. Damit bleibt die Variable erhalten und es wird durch die Funktion ein Zeiger geliefert, der auf den korrekten Speicherbereich verweist. Meine eigentliche Frage zielte ja darauf ab, warum ich den Zeiger nochmal löschen soll. Hat sich ja damit erledigt.
Delphi-Quellcode:
function getString(text:PAnsiChar):PAnsiChar; cdecl; exports getString;
var finalText:string; function getString(text:PAnsiChar):PAnsiChar; var tempText:string; Begin tempText:=WideString(text); finalText:=tempText + ' und etwas Delphi-Text'; result:=PAnsiChar(AnsiString(finalText)); End; |
AW: String-Übergabe von Delphi-DLL an C#
Zitat:
DLL:
Delphi-Quellcode:
Und das Testprojekt:
library MyDLL;
uses SysUtils, Windows; const ERROR_NO_ERROR = 0; ERROR_BUFFER_TOO_SMALL = 1; function delphi_getString(Buffer: PAnsiChar; var BufSize: DWORD): DWORD; cdecl; var Test: AnsiString; begin Test := 'Hallo Welt'; if BufSize < Length(Test) then Result := ERROR_BUFFER_TOO_SMALL else begin StrPCopy(Buffer, Test); Result := ERROR_NO_ERROR; end; BufSize := Length(Test); end; exports delphi_getString; begin end.
Delphi-Quellcode:
Wobei die Konstanten eigentlich in eine eigene Unit gehören, die von DLL und Testprojekt eingebunden wird, aber das habe ich mir hier gespart.
function delphi_getString(Buffer: PAnsiChar; var BufSize: DWORD): DWORD; cdecl;
external 'MyDLL.dll' name 'delphi_getString'; procedure TForm1.Button1Click(Sender: TObject); var s: Ansistring; BufSize: DWORD; begin BufSize := 0; delphi_getString(nil, BufSize); SetLength(s, BufSize); delphi_getString(PAnsiChar(s), BufSize); ShowMessage(s); end; |
AW: String-Übergabe von Delphi-DLL an C#
Der Absturz liegt daran, dass DeddyH die
Delphi-Quellcode:
-Aufrufkonvention verwendet hat, C# aber standardmäßig
cdecl
Delphi-Quellcode:
verwendet.
stdcall
Das hättest du entweder auf
Delphi-Quellcode:
abändern oder bei deinem DllImport-Teil bei C# anpassen müssen:
stdcall
Code:
[dllimport("mylib.dll",CallingConvention=CallingConvention.Cdecl)]
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz