AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

String-Übergabe von Delphi-DLL an C#

Ein Thema von Gargamel · begonnen am 3. Apr 2013 · letzter Beitrag vom 3. Apr 2013
Antwort Antwort
Seite 1 von 2  1 2      
Gargamel

Registriert seit: 19. Mär 2007
171 Beiträge
 
#1

String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 10:23
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:
[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);

...
Die Funktion delphi_getString sieht so aus:

Delphi-Quellcode:
function delphi_getString():PAnsiChar; cdecl; exports delphi_getString;

function delphi_getString():PAnsiChar;
var text:string;
Begin
  text:='TestString';
  result:=PAnsiChar(AnsiString(text));
End;
Was mich jetzt interessiert, ist die letzte Anweisung in dem C#-Code.

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
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#2

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 10:44
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.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 10:49
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. PAnsiChar kopiert, laut Hilfe, den String nicht, deine Funktion gibt letztendlich eine Adresse auf etwas zurück, dass wohl direkt wieder abgeräumt wird.

Mit StrNew scheint man explizit den String auf den Heap zu schreiben und dort zu lassen.

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_freeString() auch nicht.
  Mit Zitat antworten Zitat
Benutzerbild von geskill
geskill

Registriert seit: 17. Feb 2007
Ort: NRW
420 Beiträge
 
Delphi 2010 Professional
 
#4

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 11:54
Du musst in Delphi einen WideString benutzen, der passt mit den String Datentyp in C# überein.
Sebastian
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#5

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 12:25
DeddyH hat die Methode schlechthin schon angeführt - damit kommt man als DLL überall an. Nicht umsonst verwendet die WinAPI selber genau dieselbe
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#6

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 12:43
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;
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.196 Beiträge
 
Delphi 10.4 Sydney
 
#7

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 12:52
Du musst in Delphi einen WideString benutzen, der passt mit den String Datentyp in C# überein.
C# (.NET) hat zwar als Basis auch UTF-16 Strings aber auch einen OLE-Widestring muss in den .NET-String gewandelt werden damit er gemanaged ist.

Zurück zum Thema:

Ergänz mal deinen Dll-Import um die Charset-Angabe (http://msdn.microsoft.com/en-us/libr...e.charset.aspx)
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Gargamel

Registriert seit: 19. Mär 2007
171 Beiträge
 
#8

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 13:24
@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;

Geändert von Gargamel ( 3. Apr 2013 um 13:27 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#9

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 14:10
@DeddyH:

Der Code produziert leider einen Absturz.
Bei mir (Delphi XE) nicht.

DLL:
Delphi-Quellcode:
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.
Und das Testprojekt:
Delphi-Quellcode:
function delphi_getString(Buffer: PAnsiChar; var BufSize: DWORD): DWORD; cdecl;
  external 'MyDLL.dllname '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;
Wobei die Konstanten eigentlich in eine eigene Unit gehören, die von DLL und Testprojekt eingebunden wird, aber das habe ich mir hier gespart.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.159 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

AW: String-Übergabe von Delphi-DLL an C#

  Alt 3. Apr 2013, 14:15
Der Absturz liegt daran, dass DeddyH die cdecl -Aufrufkonvention verwendet hat, C# aber standardmäßig stdcall verwendet.

Das hättest du entweder auf stdcall abändern oder bei deinem DllImport-Teil bei C# anpassen müssen:
Code:
[dllimport("mylib.dll",CallingConvention=CallingConvention.Cdecl)]
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:29 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz