AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Klasseninstanz an DLL-Funktion übergeben (TStrings)
Thema durchsuchen
Ansicht
Themen-Optionen

Klasseninstanz an DLL-Funktion übergeben (TStrings)

Ein Thema von Sharky · begonnen am 1. Jan 2007 · letzter Beitrag vom 5. Jan 2007
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Sharky
Sharky

Registriert seit: 29. Mai 2002
Ort: Frankfurt
8.251 Beiträge
 
Delphi 2006 Professional
 
#1

Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 08:46
Hai ihr,

ich bin nun "gezwungen" mich endlich mit DLLs zu beschäftigen

Immer lese ich das es Probleme gibt wenn man einen Delphi-String an eine DLL übergibt bzw. zurück bekommen möchte.
Bei TStrings dürfte das aber doch kein Problem sein oder? Nicht das ich da jetzt etwas mache und auf einmal fliegt es mir um die Flossen.

Zum Beispiel habe ich diese Funktion in meiner Test-DLL
Delphi-Quellcode:
  function AddSLLines(sl: TStrings; const count: Integer): Integer; stdcall;
  var
    ndx: Integer;
    foo: Integer;
  begin
    foo := 0;
    for ndx := 1 to count do
    begin
      sl.Add(Format('Zeile %d', [ndx]));
      Inc(foo);
    end;
    Result := foo;
  end;
und rufe sie dann so in meinem Programm auf:
Delphi-Quellcode:
  TAddSLLines = function(sl: TStrings; count: Integer): Integer; stdcall;

  TForm1 = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  dllHandle: THandle = -1;
  AddSLLines: TAddSLLines = NIL;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AddSLLines(ListBox1.Items, 10);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  pfad: string;
begin
  pfad := IncludeTrailingBackslash(ExtractFilePath(ParamStr(0))) + 'test.dll';
  dllHandle := LoadLibrary(PAnsiChar(pfad));
  if dllHandle <> 0 then
  begin
    @AddSLLines := GetProcAddress(dllHandle, 'AddSLLines');
  end
  else
  begin
    ShowMessage('blubb');
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeLibrary(dllHandle);
end;
Ist das okay so oder habe ich da einen groben Fehler?
Stephan B.
"Lasst den Gänsen ihre Füßchen"
  Mit Zitat antworten Zitat
Reinhard Kern

Registriert seit: 22. Okt 2006
772 Beiträge
 
#2

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 09:18
Zitat von Sharky:
Hai ihr,

ich bin nun "gezwungen" mich endlich mit DLLs zu beschäftigen ;-)

Immer lese ich das es Probleme gibt wenn man einen Delphi-String an eine DLL übergibt bzw. zurück bekommen möchte.
Bei TStrings dürfte das aber doch kein Problem sein oder? Nicht das ich da jetzt etwas mache und auf einmal fliegt es mir um die Flossen.
...

Ist das okay so oder habe ich da einen groben Fehler?
Hallo,

so allgemein für DLLs kann man das nicht sagen, aber Strings sind nun mal Pascal-spezifisch, in anderen Programmiersprachen, besonders die Cs, sind nullterminierte Zeichenfolgen üblich bzw. Pointer darauf. Die gibt es in Pascal als PChar auch schon lange, aber string und PChar sind getrennte Welten mit unterschiedlichen Funktionen.

Besonders das Win32 API benutzt ausschliesslich PChar, das hat auch technische Vorteile gegenüber der Übergabe von Pascal-Strings an/von DLLs. Du must eben immer umwandeln (der Compiler weist dich schon drauf hin), oder du schreibst dir "Wrapper" wie z.B.
Delphi-Quellcode:
function LoadLibrary_ss (LibPath : ShortString) : THandle;
var lparr : array [0..255] of char;
begin
StrPLCopy (lparr,LibPath,255);
Result := LoadLibrary (lparr);
end;
aber das lohnt sich nur, wenn du die Funktion oft brauchst.

Du hast etwas anders umgewandelt, aber das muss ebenfalls funktionieren. Je nach Aufgabe könnte man in Delphi auch ganz mit arrays und PChar programmieren, aber für Pascal-Strings gibt es mehr Funktionen.

Gruss Reinhard
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.851 Beiträge
 
Delphi 11 Alexandria
 
#3

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 10:58
Im Falle von TStrings muß er dann die einzelnen Strings der Stringliste als einen Array von PChars übergeben
Markus Kinzler
  Mit Zitat antworten Zitat
Reinhard Kern

Registriert seit: 22. Okt 2006
772 Beiträge
 
#4

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 14:03
Zitat von mkinzler:
Im Falle von TStrings muß er dann die einzelnen Strings der Stringliste als einen Array von PChars übergeben
Hallo,

korrigiere mich, wenn ich was Falsches sage:

Man kann schon eine Delphi-DLL erstellen, die als Parameter Delphi-Objekte verwendet - aber erstens muss man sich dann sehr sorgfältig überlegen, wann und wo Create und Destroy stattfinden, und ausserdem ist diese DLL natürlich mit keiner anderen Programmiersprache verwendbar, sondern kann nur von Delphi-Programmen aufgerufen werden. Das ist meistens nicht der Sinn einer DLL.

Andere Sprachen kennen Delphi-Objekte grundsätzlich nicht (kein einziges!), also kann man so etwas wie TStrings eben nicht als Parameter definieren und muss praktisch die Software so umbauen, dass zumindest an den Schnittstellen keine Objekte verwendet werden (gilt für andere OO-Sprachen genauso). TStrings als array of PChar zu übergeben, ist schon der richtige Rat, aber noch lang nicht alles; dieses array ist eben keineswegs ein TStrings-Objekt - das müsste man erst wieder zusammensetzen, oder man schreibt die Software eben um für die direkte Verwendung des arrays. Man muss also sozusagen die Objekte aufbrechen in einfache Datentypen, das Komplexeste ist ein Record.

Gruss Reinhard
  Mit Zitat antworten Zitat
Jürgen Thomas

Registriert seit: 13. Jul 2006
Ort: Berlin
750 Beiträge
 
#5

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 14:18
Zunächst einmal Frohes Neues Jahr!

Ihr habt natürlich alle recht mit der Übergabe von Strings per DLL. Aber bei TStrings kann man es sich doch etwas einfacher machen:
Delphi-Quellcode:
var aListe: TStrings;
// übergeben
pc := PChar(aListe.Text);
// übernehmen
aListe.Text := StrPas(pc);
Gruß Jürgen

PS. Bitte nicht sauer sein, wenn es nicht ganz korrekt ist: Ich bin seit einem Jahr fast ausschließlich mit C# befasst; und wegen dieser Probleme habe ich auch vorher mich sehr bemüht, auf string-Übergabe an DLL zu verzichten.
#D mit C# für NET, dazu Firebird
früher: Delphi 5 Pro, Delphi 2005 Pro mit C# (also NET 1.1)
Bitte nicht sauer sein, wenn ich mich bei Delphi-Schreibweisen verhaue; ich bin inzwischen an C# gewöhnt.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#6

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 14:23
Will man mit Objekten in DLLs arbeiten, wären Laufzeitpackages die bessere Wahl.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
bigg
(Gast)

n/a Beiträge
 
#7

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 14:23
Hi jürgen,

"TStrings.Text()" ruft die Methode der Klasse TStrings auf und erzeugt den "Gesamt-Text". Das mag zwar funktionieren ist allerdings deutlich langsamer.


Mfg Stefan
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
17.171 Beiträge
 
Delphi 10.4 Sydney
 
#8

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 14:24
Zitat von Reinhard Kern:
korrigiere mich, wenn ich was Falsches sage:

Man kann schon eine Delphi-DLL erstellen, die als Parameter Delphi-Objekte verwendet - aber erstens muss man sich dann sehr sorgfältig überlegen, wann und wo Create und Destroy stattfinden, und ausserdem ist diese DLL natürlich mit keiner anderen Programmiersprache verwendbar, sondern kann nur von Delphi-Programmen aufgerufen werden. Das ist meistens nicht der Sinn einer DLL.
Es gibt noch mehr Einschränkungen:
- Exe + DLL müssen mit der gleichen Delphi-Version erzeugt worden sein damit das Speicherlayout der Instanzen gleich ist
- Die Is/As-Operationen funktionieren nicht, da Exe und DLL (wenn keine Laufzeitpackages verwendet werden) unabhänige Klassenmodelle haben. (TObject Exe <> TObject DLL).

Zitat von Reinhard Kern:
... und muss praktisch die Software so umbauen, dass zumindest an den Schnittstellen keine Objekte verwendet werden (gilt für andere OO-Sprachen genauso).
Deshalb hat ja z.B. MS mit COM eine Definition geschaffen die es ermöglich Objekte zwischen verschiedenen Sprachen austauschen zu können. Die konsequente Weiterentwicklung dieses Gedankens ist .NET wo viele Nachteile von COM (Registry, Admin-Rechte, ...) nicht mehr gegeben sind.

Zitat von Reinhard Kern:
... oder man schreibt die Software eben um für die direkte Verwendung des arrays. Man muss also sozusagen die Objekte aufbrechen in einfache Datentypen, das Komplexeste ist ein Record.
Oder man Schreibt auf beiden Seiten diser DLL-Schnittstelle Schnittstellen-Objekte welche diese Umsetzung durchführen. Nach "oben" wird eine Objekt verwendet welche zur übertragung DLL serialisiert wird und in der DLL wieder zusammengesetzt wird.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#9

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 1. Jan 2007, 19:36
Ich habe gerade kein Delphi hier. (hier <> @home )
Muss mir das also etwas aus den Fingern saugen....
Was Bernhard da angesprochen hat lässt sich auch ohne COM realisieren. Delphi Interfaces erfüllen die COM-Pflichten, sie sind also binär kompatibel zueinander. Auch wenn du sie in 2 Binaries kompilierst (Deine Echse und die DLL).
Du benutzt in der Methode oben eigentlich nur die Methode Add von TSTrings. Das Interface was man hier braucht müsste also nur die Methode Add besitzen:
Delphi-Quellcode:
type
  IStringList = interface(IUnknown)
  ['bli-bla-blubb'] //hier ctrl+g drücken ;)
    function Add(const aString : String) : Integer;
  end;
Solange Delphi mit Delphi in der gleichen Version "redet" kann man String benutzen, solange ShareMem/FastMM als erste Unit in der DLL und in der Echse verwendet wird.
Die StringList version, die du in der Echse benutzt, muss natürlich noch das Interface implementieren.
Da ich (hoffentlich) die gleiche Signatur der Methode in dem Interface habe, wie sie bereits in TStrings deklariert ist, sollte das ziemlich easy sein:
Delphi-Quellcode:
type
  TMyStringlist = class(TStringList , IStringList)
  private
    fStringList : TStringList;
  protected
   // hier die Methoden von System.TInterfacedObject reinkopieren
  public
    constructor Create;
    destructor Destroy; override;
  end;
...
constructor TMyStringlist.Create;
begin
  fStringList := TStringList.Create();
end;

destructor TMyStringlist.Destroy;
begin
  fStringList.Free();
end;
Die Unit mit dem Interface kannst du in Echse und DLL benutzen. Die TMyStringList sollte aber niemals direkt zwischen den beiden übergeben werden sondern nur als Referenz auf IStringList.
Wenn du es übergibst, sollte der Parameter immer schön als "const" übergeben werden. Dadurch findet keine Referenzzählung statt und Delphi wird dir beim erreichen der 0 nicht die Instanz töten, obwohl du damit wahrscheinlich noch arbeiten willst.
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#10

Re: Klasseninstanz an DLL-Funktion übergeben (TStrings)

  Alt 4. Jan 2007, 18:44
Sharky, wenn ich etwas übersetzen muss, einfach laut schreien.
Wenigstens einmal/d kieke ich in die DP.
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  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 09:09 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