Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Typinformation von Records (https://www.delphipraxis.net/100261-typinformation-von-records.html)

jensw_2000 25. Sep 2007 12:28


Typinformation von Records
 
Ich habe hier (klick) eine Unit von Sirius gefunden, mit der man dynamische Strukturen komfortabel in einen Stream packen kann.
Bleibt das Problem, das TypeInfo(TMyRecord) nur funktioniert, wenn der Record einen Member vom Typ Variant hat.

Beispiel:

Delphi-Quellcode:
Type
  TMyRecord1 = packed Record
    aInteger   : integer;
    aString    : String[100];
  end;

...

Typeinfo(TMyRecord1)    >>>> Der Typ TMyRecord1 enthält keine TypInformation.
Delphi-Quellcode:
Type
  TMyRecord2 = packed Record
    Dummy      : variant;
    aInteger   : integer;
    aString    : String[100];
  end;

Typeinfo(TMyRecord2)     >>>> geht
Warum ist das so ?
Kann ich irgendwie an die Typinformation kommen ohne einen Variant in den Record zu stecken ?

Der Record wird als Parameter zum Aufruf einer DLL Prozedur verwendet. Die DLL verwendet kein Sharemem. Daher habe ich etwas Respekt vor dem Variant, weil der der geneigte "DLL Benutzer" versuchen könnte, lange Strings über den Variant zu transportieren.



Schöne Grüße,
Jens
:hi:

Sidorion 25. Sep 2007 13:35

Re: Typinformation von Records
 
Hättest Du mal die OH für die Fehlermeldung gelesen, wüsstest Du, dass Records keine Typinformationen bereitstellen. Versuch mal, den Schalter M (TYPEINFO) anzuschalten, also:
Delphi-Quellcode:
{M+}
   TMyRecord1 = packed Record
    aInteger   : integer;
    aString    : String[100];
  end;
{M-}
Wenn das nicht klappt (wovon ich ausgehe, da Records keine published, sondern public Member haben), empfehle ich, den Record als Puffer und die Länge des Typs (sizeof) zu übergeben.

jensw_2000 25. Sep 2007 14:22

Re: Typinformation von Records
 
Die Hilfe zu dem Fehler habe ich schon gelesen. Hätte mich auch fast damit zufrieden gegeben, aber es gibt hier in der DP einige Beiträge (z.B. hier), in denen Typeinfo(TEinRecord) offensichtlich funktioniert.
Generell geht es bei mir ja auch, sobald ich einen "Dummy"-Member" von Typ Variant mit in den Record lege.
Und genau das würde ich gerne verstehen.
Warum geht es "nur" mit mindestens einem Variant-Member, bzw. wie kann ich diesen Effekt auch ohne Variant-Member erreichen ?

PS: Die Compiler-Direktiven {M+} {M-} helfen nicht ....

Hawkeye219 25. Sep 2007 14:38

Re: Typinformation von Records
 
Hallo Jens,

der Compiler generiert (eingeschränkte) Typinformationen für Records immer dann, wenn der Record Elemente enthält, die finalisiert werden müssen (z.B. Variants, dynamische Strings oder Arrays).

Zitat:

[...]aber es gibt hier in der DP einige Beiträge (z.B. hier), in denen Typeinfo(TEinRecord) offensichtlich funktioniert.
Nicht offensichtlich, nur scheinbar...

Gruß Hawkeye

Apollonius 25. Sep 2007 14:47

Re: Typinformation von Records
 
Der Grund ist, das referenzgezählte Typen aufgeräumt werden müssen. Beispiel: Ich habe eine lokale Variable als Record deklariert, der ein IInterface-Feld besitzt. Wenn ich diesem Feld etwas zuweise, greift die Referenzzählung. Wenn ich die Routine verlasse, muss der Referenzzähler dekrementiert werden. Dies wird erledigt, indem auf die Typinformation zugegriffen wird. Wenn jedoch kein Feld, welches aufgeräumt werden muss, im Record enthalten ist, dann wird die Typinformation intern nicht benötigt.
Referenzgezählte Typen sind dynamische Arrays, Interfaces und Ansistrings. Bei Varianten bin ich mir ehrlich gesagt nicht ganz sicher, ich habe mich mit ihnen nie näher auseinandergesetzt.
Wenn du keine Lösung finden solltest, dann nimm lieber einen der oben genannten Typen, diese sind nur 4 Byte, statt 16 Bytes bei Variants, groß.

jensw_2000 25. Sep 2007 15:03

Re: Typinformation von Records
 
Danke, das bringt Licht ins Dunkel.

Mal schauen ob ich dann lieber eine Klasse verwende oder den Record einfach "blind" mit MyRecord,sizeof(TMyRecord) speichere.

@Hawkeye219
Bedeutet "eingeschränkte Typinformationen", dass die Typeinformation nur Informationen über die zu finalisierenden Member enthält?

Hawkeye219 25. Sep 2007 15:32

Re: Typinformation von Records
 
Den genauen Aufbau der Strukturen kenne ich leider nicht. Nach meinem Wissen enthalten sie nur die wirklich notwendigen Daten (Record-Größe, Informationen über die zu intialisierenden/finalisierenden Felder), aber keine Feldnamen oder Typinformationen für die übrigen Felder.

Vielleicht kein negaH noch etwas beisteuern, ansonsten schaue mal bei Hallvard Vassbotn vorbei.

Gruß Hawkeye

Apollonius 25. Sep 2007 16:06

Re: Typinformation von Records
 
Wenn man Assembler kann, dann sieht man in der automatisch aufgerufenen Routine FinalizeRecord sehr deutlich den Aufbau. Hier meine Umsetzung:
Delphi-Quellcode:
type
TFinalField = packed record
  Typ: PPTypeInfo; //Beachte den Zeiger auf den Zeiger!
  Offset: integer;
end;

TRecordTypeData = packed record
  RecSize: integer;
  FinalFieldCount: integer;
  FinalFields: array[0..MaxWord div sizeof(TFinalField)-1] of TFinalField;
  //Eigentlich:
  //FinalFields: array[0..FinalFieldCount-1] of TFinalField;
end;

procedure dumpRecTypeData(p: PTypeData);
var i: integer;
begin
writeln('Size: ', PInteger(p)^);
writeln('Number of fields to finalize: ', PInteger(Integer(p)+4)^);
for i:=1 to PInteger(Integer(p)+4)^ do
 begin
  writeln;
  writeln('Offset: ', PInteger(integer(p)+12)^);
  writeln('PTypeInfo: ', inttohex(PInteger(PPointer(integer(p)+8))^, 8));
  inc(integer(p), 8);
 end;
end;
Es werden also wirklich nur die Felder gespeichert, die finalisiert werden müssen.


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