Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Record aus DLL "importieren" (https://www.delphipraxis.net/115191-record-aus-dll-importieren.html)

S20000 7. Jun 2008 18:38


Record aus DLL "importieren"
 
Hallo zusammen,

ich habe eine Frage zur DLL Programmierung.

Angenommen jemand gibt mir eine DLL deren Funktionen ich kenne.
Die DLL ist in C programmiert und ich möchte sie in Delphi einbinden.

In der DLL wird z.B. ein Record angelegt:

Delphi-Quellcode:
//C-Code:

type Personen=record
     Name:string;  
     Vorname:string;
end;

...
Person1.Name='20000'
Person1.Vorname='Sebastian';

// "Zeiger PREC zeigt auf Person1"
Mit Hilfe einer Funktion, deren Name und Parameter ich kenne wird
ein Zeiger (z.B. PREC), der ein Parameter ist, auf das Record gelegt.

Meine Frage ist nun, wenn ich diese DLL-Funktion aus Delphi heraus aufrufe,
wird mir der Zeiger PREC auf ein Record üermittelt.
Wie sage ich Dephi nun, das hinter dem Zeiger ein Record steckt?
Wie greife ich z.B. auf den Vornamen von Person 1 zu?

Kann ich einfach sagen:

Delphi-Quellcode:
showmessage(PREC^.Name); ??
Ich hoffe die Frage wurde verständlich.


Gruß
Sebastian

Christian Seehase 7. Jun 2008 18:58

Re: Record aus DLL "importieren"
 
Moin Sebastian,

diese Konstellation hast Du bei vielen API-Funktionen auch.
Damit die Funktion etwas in den Record speichern kann gibt es zwei Möglichkeiten:
  1. Du reservierst Speicher, und übergibst diese Adresse an die Funktion, damit sie dort Daten reinschreiben kann.
  2. Du übergibst die Adresse einer Variablen, und die Funktion reserviert auch den Speicher, bevor sie Daten in den Record schreibt, und gibt dann diese Adresse zurück.

Der erste Fall ist der üblichere, der zweite tritt vornehmlich bei der LAN-Manager-API auf.
In jedem Falle musst Du dann auch den Speicher wieder freigeben.

Beispiel:

Delphi-Quellcode:
Type
  PMyRecord = ^TMyRecord;
  TMyRecord = packed record
    cbNameSize : DWORD; // hierüber erfährt die Funktion, wieviel Speicher für lpName reserviert wurde
    lpName    : PChar; // hier kann die Funktion dann etwas zurückliefern.
  end;

function ImportierteDLLFunktion(const AMyRecord : PMyRecord) : Integer; stdcall; external 'DLLNAME.DLL';

procedure Irgendwas;

var
  mr : TMyRecord;

begin
  FillChar(mr,SizeOf(mr),0); // Kann i.d.R. entfallen, wenn man alle Felder des Records verwendet
  mr.cbName := 100; // Die Funktion bekommt 99 Zeichen Speicher (zzgl. der abschliessenden 0)
  mr.lpName := AllocMem(mr.cbName); // Jetzt noch den Speicher reservieren
  try
    // Der Funktion wird die Adresse des Records übergeben
    if ImportierteDLLFunktion(@mr) = 0 then begin // mal angenommen 0 sagt aus: Alles OK
      ShowMessage(mr.lpName);
    end else begin
      ShowMessage('Fehler');
    end;
  finally
    FreeMem(mr.lpName,mr.cbName);
  end;
end;

Luckie 7. Jun 2008 19:03

Re: Record aus DLL "importieren"
 
Probleme dürften allerdings die Strings in dem Record bereiten, deswegen nimm lieber PChars, wie es Christian in seinem Beispiel auch gemacht hat.

oki 7. Jun 2008 19:16

Re: Record aus DLL "importieren"
 
Ich denke Christian ist ein kleiner Fehler unterlaufen.
Dies:
Delphi-Quellcode:
var
  mr : MyRecord;
sollte wohl so aussehen:
Delphi-Quellcode:
var
  mr : TMyRecord;
Gruß oki

Christian Seehase 7. Jun 2008 19:17

Re: Record aus DLL "importieren"
 
Zitat:

Zitat von oki
Ich denke Christian ist ein kleiner Fehler unterlaufen.
Dies:
Delphi-Quellcode:
var
  mr : MyRecord;
sollte wohl so aussehen:
Delphi-Quellcode:
var
  mr : TMyRecord;
Gruß oki

Stümmt :oops:

Hab' ich korrigiert.

S20000 8. Jun 2008 12:40

Re: Record aus DLL "importieren"
 
Vielen Dank!

Wie siehts im Falle aus, dass die DLL das Record anlegt und den Speicher reserviert und
mir den Pointer auf das Record gibt.

Würde dann der Zugriff auch so funktionieren:

Delphi-Quellcode:
ShowMessage(mr.lpName);
Oder muss Delphi bekannt gemacht werden das hinter dem Pointer ein Record steckt?

Gruß
Sebastian

oki 8. Jun 2008 16:26

Re: Record aus DLL "importieren"
 
mr ist vom Typ TMyRecord und somit weiß Delphi Bescheid. An dieser Stelle würde ich dann aber eher folgendes machen:
Delphi-Quellcode:
var
  mr : PMyRecord;
begin
  ....
  if ImportierteDLLFunktion(mr) = 0 then begin // mal angenommen 0 sagt aus: Alles OK
  ShowMessage(mr^.lpName);
  ...
Imho ist es aber eher üblich, dass die Anwendung den Speicher reserviert. In diesem Beispiel ist es so, dass du eine Variable vom Typ Pointer übergibst. Die Funktion würde dir in dieser dann die Adresse zurückliefern die auf den Speicherbereich mit den Daten zeigt.
Da PMyRecord eine Zeigervariable auf einen Record vom Typ TMyRecord ist kannst du über den Referenzzeiger wie gewohnt auf die einzelnen Parameter zugreifen.

Gruß oki


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:31 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