Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Records und RTTI? (https://www.delphipraxis.net/74504-records-und-rtti.html)

3_of_8 4. Aug 2006 00:26


Records und RTTI?
 
Morgen.

Mich würde es mal interessieren, inwiefern ein (packed) record einen RTTI Eintrag besitzt und, wenn er einen hat, wie ich ihn auslesen kann.

JasonDX 4. Aug 2006 05:22

Re: Records und RTTI?
 
afaik besitzt ein Record keinen. Elemente eines Records besitzen lediglich offsets, die wie eine Variable direkt übersetzt werden.
Ein Blick ins CPU-Fenster gibt:
Delphi-Quellcode:
h = packed record
  i: integer;
  s: smallint;
end;

var
  m: h;

m.i := 0;
m.s := 1;
gibt
Code:
xor eax, eax
mov [m], eax
mov word ptr [m + $4], $0001
Es wird also direkt gesagt: i liegt direkt hinter der Adresse von m. s liegt dann 4 Byte weiter. Ein Record wird so eben auch im Speicher abgebildet, ohne zusätzliche Informationen oder ähnliches.
Aber wenn man sich die Prozeduren der TypInfo-Unit anguckt, merkt man bald, dass die Zugriffe nicht über Pointer oder ähnliches, sondern über TObject laufen, was darauf schließen lässt, dass der Spaß nur mit Klassen wirklich auch Spaß bringt. ;)

greetz
Mike

3_of_8 4. Aug 2006 10:28

Re: Records und RTTI?
 
Den Offset kriege ich praktisch mit:
Delphi-Quellcode:
function GetOffset(var rec, recvar): Integer;
asm
sub edx, eax
mov eax, edx
end;

himitsu 4. Aug 2006 11:25

Re: Records und RTTI?
 
Zitat:

Zitat von JasonDX
afaik besitzt ein Record keinen.

nicht?

aber woher weiß dann alles, daß es hier den String initialisieren und natürlich auch finalisieren muß?
Oder wird das dann hardgecodet, also einfach nur überall die Init-/Finalisierung hingeschrieben?
Delphi-Quellcode:
h = {packed or nich} record
  i: integer;
  s: string;
end;

jbg 4. Aug 2006 11:34

Re: Records und RTTI?
 
Zitat:

Zitat von himitsu
Zitat:

Zitat von JasonDX
afaik besitzt ein Record keinen.

nicht?

Ein Record besitzt sehr wohl eine RTTI. Jedoch nur wenn er Datentypen enthält, die eine Finalisierung benötigen.

JasonDX 4. Aug 2006 11:42

Re: Records und RTTI?
 
Zitat:

Zitat von jbg
Ein Record besitzt sehr wohl eine RTTI. Jedoch nur wenn er Datentypen enthält, die eine Finalisierung benötigen.

Oha :oops: Wie heissts so schoen: wenn man keine Ahnung hat :duck:
Na ja, halbs richtig aber, reicht auch schon fuer die fruehe Uhrzeit *g*
Aber mal aus reiner Neugierde: Kann ich auf diese TypeInfo auch zugreifen? Wenn ich mich nicht ganz verschaut hab, dann wird in der TypInfo-Unit alles ueber TObject gehandhabt. Geht das (und wenn, wie) auch bei dementsprechenden Records?

greetz
Mike

jbg 4. Aug 2006 11:48

Re: Records und RTTI?
 
Zitat:

Zitat von JasonDX
Kann ich auf diese TypeInfo auch zugreifen?

Wenn eine existiert: Ja.

Zitat:

Wenn ich mich nicht ganz verschaut hab, dann wird in der TypInfo-Unit alles ueber TObject gehandhabt.
Dem ist so.

Zitat:

Geht das (und wenn, wie) auch bei dementsprechenden Records?
Nicht mit den Infos aus der TypInfo.pas.

Die notwendigen Datentypen findest du in der System.pas direkt über _InitializeRecord(). Und _InitializeRecord() zeigt dir, wie du die den RTTI-Zeiger ermitteln kannst.

stoxx 13. Feb 2009 00:49

Re: Records und RTTI?
 
Zitat:

Die notwendigen Datentypen findest du in der System.pas direkt über _InitializeRecord(). Und _InitializeRecord() zeigt dir, wie du die den RTTI-Zeiger ermitteln kannst
ähm .. und wie geht das da mit InitializeRecord? *guck*

:nerd:

stoxx 13. Feb 2009 01:14

Re: Records und RTTI?
 
bei diesem Code ist in der PropList nur MyDouble vorhanden.
Wie kann man den Record auch noch regiestrieren? Damit er in die Liste kommt?

Hier mal der Code:


Delphi-Quellcode:

uses
  typinfo;

type

 TMyRecord = record
   Value1 : Integer;
   Value2 : Integer;
 end;

 TMyClass = class(TPersistent)
 private
   FDouble : Double;
   FMyRecord : TMyRecord;

 published
   property MyDouble : Double read FDouble write FDouble;
   property MyRecord : TMyRecord read FMyRecord write FMyRecord;

 end;


procedure TForm1.btnRTTIClick(Sender: TObject);
  var
    i, Count: Integer;
    PropList: PPropList;

    s:string;
    sl : TStringList;

    myObject : TMyClass;
    typeInfo : PTypeInfo;
  begin


    sl := TStringList.Create;

    myObject := TMyClass.Create;
    TypeInfo := myObject.ClassInfo;

    Count := GetPropList(typeInfo ,tkProperties,nil);
    GetMem(PropList, Count * SizeOf(PPropInfo));

    GetPropList(TypeInfo, tkProperties, PropList);

    for I := 1 to Count do begin
        s := PropList^[i - 1].Name;
        sl.Add(s);
    end;


    ShowMessage(sl.Text);

    FreeMem(PropList);
    myobject.free;
    sl.Free;
end;

sirius 13. Feb 2009 07:13

Re: Records und RTTI?
 
Ein Beitrag von mir in der Codelib nutzt die RTTI der Records umd diese in einem Stream zu speichern.

stoxx 13. Feb 2009 12:00

Re: Records und RTTI?
 
Hi Sirius,

das Verfahren ist mir noch nicht ganz klar. Würde es denn gehen, und wenn ja wie, dass die
property MyRecord mit in der Liste bei "GetPropList" erscheint?
Was meinst Du?

sirius 13. Feb 2009 12:03

Re: Records und RTTI?
 
Leg in TmyRecord mal einen String rein und schaus dir an!

stoxx 13. Feb 2009 12:39

Re: Records und RTTI?
 
Zitat:

Zitat von sirius
Leg in TmyRecord mal einen String rein und schaus dir an!

hmm .. naja .. Bedingung wäre, TMyRecord nicht zu verändern.
Es handelt sich bei uns um 2 oder 3 neue Standarddatentypen. so wie Double..

Ich hab auch schon geschaut ob man die Unit TypInfo ergänzen und /oder neu compilieren könnte.
Bin da aber nicht weiter gekommen.

Da gibts so SetFloatProp proceduren, bin aber da nicht weitergekommen.
Liegt sowas im Rahmen der Möglichkeiten? oder völlig aussichtslos?

Delphi-Quellcode:
procedure SetFloatProp(Instance: TObject; const PropName: string;
  const Value: Extended);
begin
  SetFloatProp(Instance, FindPropInfo(Instance, PropName), Value);
end;
ich würde gern auch die TTypeKind um einen oder zwei neue Typen erweitern

Delphi-Quellcode:
type
  TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat,
    tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString,
    tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray);

sirius 13. Feb 2009 12:42

Re: Records und RTTI?
 
Zitat:

Zitat von stoxx
Liegt sowas im Rahmen der Möglichkeiten? oder völlig aussichtslos?

Wenn der Record so bleibt, ist es aussichtslos.

Delphi unterscheidet strikt zwischen Record mit dynamischen Inhalten (dynamische Arrays, Strings, Interfaces, Variant) und den anderen Records.

stoxx 13. Feb 2009 12:53

Re: Records und RTTI?
 
Zitat:

Zitat von sirius
Wenn der Record so bleibt, ist es aussichtslos.


und wenn man "ganz" viel Aufwand betreiben würde, und die VCL komplett neu compilieren würde?
Und die Unit TypInfo um einen eigenen Typ erweitern würde?

Double hat ja auch keinen eigenen String.

Würde das dann möglich sein, oder spielt der Compiler dann nicht mit?

Die neuen Möglichkeiten der Operatorenüberladung bieten halt schöne Möglichkeiten eines neuen Datentyps.

sirius 13. Feb 2009 12:55

Re: Records und RTTI?
 
Vielleicht (irgendwie gibt es ja auch myDouble), aber ich hab vor Montag keine Zeit da genauer drüber nachzudenken.

stoxx 13. Feb 2009 13:27

Re: Records und RTTI?
 
ok, ich danke Dir :-)
ich guck da Montag nochmal ;-)

stoxx 16. Feb 2009 12:41

Re: Records und RTTI?
 
Hi Sirius,

ich wollte Dich nochmal fragen, warum der Typ nicht als tkRecord im RTTI System auftaucht?
Muss man den Typ vorher irgendwo registrieren, damit er erfasst wird?
tkRecord muss ja irgendwie einen Sinn haben, oder?

:-)

Danke !

sirius 16. Feb 2009 13:15

Re: Records und RTTI?
 
Sieht schlecht aus. In meinem verlinkten Code hatte ich sowieso die InitTable benutzt (da taucht auch kein double auf, weil es ja weder initialisiert noch finaliziert werden muss).
Bei den published properties (und Methoden) sind mir auch schon ein paar Ungereimtheiten aufgefallen. Z.B. werden bei manchen Methode die Paramter gespeichert ({MethodInfo on}) bei anderen nicht. Das Record scheint etwas besonderes an sich zu haben. Ändern kann man das meiner Meinung nach nicht. Der compiler arbeitet hier ganz autark und legt die RTTI so an, wie er sie benötigt. Die Unit TypInfo eröffnet nur eine Möglichkeit darauf zuzugreifen, sie ist aber keine Vorraussetzung für das Arbeiten des Compilers bzw. das Anlegen der RTTI.

stoxx 16. Feb 2009 14:46

Re: Records und RTTI?
 
und man kann diese PropList nicht nachträglich patchen irgendwie? indem man den Eintrag hinzufügt?
Meine Kenntnisse sind dafür zu gering, aber die Liste muss doch irgendwo sein
die Funktion GetPropInfos ist dann leider Assembler :-(

aus Typinfo

Delphi-Quellcode:
function GetPropList(TypeInfo: PTypeInfo; out PropList: PPropList): Integer;
begin
  Result := GetTypeData(TypeInfo)^.PropCount;
  if Result > 0 then
  begin
    GetMem(PropList, Result * SizeOf(Pointer));
    GetPropInfos(TypeInfo, PropList);
  end;
end;

sirius 16. Feb 2009 14:52

Re: Records und RTTI?
 
Die RTTI sind Informationen zur Klasse, welche vom Compiler erzeugt werden. Und da ist tatsächlich eine Liste. Aber die kann man nicht erweitern, außer man schreibt sich einen eigenen Compiler.

aus der Delphi-Hilfe:
Zitat:

published-Eigenschaften sind auf bestimmte Datentypen beschränkt. Ordinal-, String-, Klassen-, Schnittstellen- Variant- und Methodenzeigertypen können mit dieser Sichtbarkeit deklariert werden. Bei Mengentypen ist dies nur möglich, wenn die Ober- und Untergrenze des Basistyps einen Ordinalwert zwischen 0 und 31 hat. (Die Menge muss also in ein Byte, Wort oder Doppelwort passen.) Auch alle Real-Typen außer Real48 können als published deklariert werden. Für Eigenschaften von Array-Typen ist published dagegen nicht zulässig (im Gegensatz zu den weiter unten beschriebenen Array-Eigenschaften).

Einige Eigenschaften, die als published deklariert werden können, werden vom Streaming-System nicht voll unterstützt. Dazu gehören die Eigenschaften von record-Typen, die Array-Eigenschaften aller als published deklarierbaren Typen und die Eigenschaften von Aufzählungstypen, die anonyme Werte enthalten. Wenn Sie eine derartige Eigenschaft als published deklarieren, wird sie im Objektinspektor nicht korrekt angezeigt, und ihr Wert geht beim Schreiben des Streams auf die Festplatte verloren.


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