Entwickler-Ecke

Free Pascal - tgPuttyLib merkwürdige Struktur


icho2099 - Do 16.07.20 18:08
Titel: tgPuttyLib merkwürdige Struktur
Hallo, ich hoffe es kann mir jemand auf die Sprünge helfen.
Ich habe die tgPuttyLib (sftp Klasse) und finde darin eine Struktur, die ich zusammen mit dem Beispiel nicht verstehe.
Zunächst die Deklaration:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
type fxp_attrs=record
                 flags:UInt32;
                 size: UInt64;
                 uid,gid,
                 permissions,
                 atime,mtime:UInt32;
               end;
     Pfxp_attrs=^fxp_attrs;

     fxp_name=record
                filename,longname:PAnsiChar;    //zwei Strings 
                attrs            :fxp_attrs;    //ein Record für Attribute
              end;
     Pfxp_name=^fxp_name;

     fxp_names=record
                 nnames:Integer;                 //number of names ??? count ?
                 names:Pfxp_name;                //pointer auf record fxp_name
               end;
     Pfxp_names=^fxp_names;


Dann die Frage:
In einem Beispiel wird das so verwendet:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function TTester.ListingCallback(const names:Pfxp_names):Boolean;
var i:Integer;
begin
  for i:=0 to names^.nnames-1 do
    WriteLn(names^.names[i].filename:40,'  ',names^.names[i].attrs.size:10);
  Result:=true;
  end;


Der Teil names.names[i] wird vom Compiler, meiner Meinung nach zu Recht, angemeckert, weil in der
Deklaration gibt es kein Array das man indizieren könnte. "Error: Array type required"

Andererseits enthält die Deklaration mit nnames ja ein
Feld welches die Anzahl der Records angeben soll(te), mit names:Pfxp_name aber nur einen Pointer auf ein fxp_name Record.
Und das enthält auch keine weiteren Pointer die eine Liste bilden könnten.

Ohne den Index liefert mir names.names.filename einen Dateinamen, der auch stimmt. Aber nur den einen obwohl nnames 4 liefert.
Wie names zusammengestöpselt wird kann ich nicht sagen, das verbirgt sich in der tgputtylib.dll
Gibt es da in Delphi vielleicht eine gewisse Magie, die names indizierbar macht ohne das zu deklarieren? Und wenn ja, wie
bringt man das dann dem Larzarus/fpc bei?
Habe da einen Knoten im Hirn, komme nicht drauf wie das richtig funktionieren soll. Wäre für Hilfe und Tips dankbar.


Th69 - Do 16.07.20 19:47

Das ist, wie in C, ein Zeiger auf einen dynamisch allozierten Bereich (Array), d.h. die einzelnen record-Elemente liegen hintereinander im Speicher und können über den Index angesprochen werden (und dafür auch zusätzlich die Variable nnames, um die Größe zu speichern bzw. den Wertebereich der Indizes zu wissen).

Der Speicher wird dann wohl mittels GetMem [http://www.delphibasics.co.uk/RTL.asp?Name=GetMem] angelegt worden sein.

Da du schreibst, daß Lazarus (bzw. genauer 'Free Pascal') das nicht unterstützt, wirst du wohl dann die Syntax für ein dynamisches Array [https://wiki.freepascal.org/Dynamic_array] dort benutzen müssen.

Edit: Für Delphi muß man wohl {$POINTERMATH ON} aktivieren, s. Pointer Math (Delphi) [http://docwiki.embarcadero.com/RADStudio/Rio/en/Pointer_Math_(Delphi)]. Dies sollte auch bei Free Pascal so funktionieren: The POINTERARITHMETICS mode switch has been replaced with the POINTERMATH directive [https://wiki.freepascal.org/User_Changes_2.6.0#The_POINTERARITHMETICS_mode_switch_has_been_replaced_with_the_POINTERMATH_directive].


icho2099 - Fr 17.07.20 11:26

Besten Dank user profile iconTh69

{$POINTERMATH ON} ist die Lösung.