![]() |
Typinformation von Records
Ich habe
![]() 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:
Warum ist das so ?
Type
TMyRecord2 = packed Record Dummy : variant; aInteger : integer; aString : String[100]; end; Typeinfo(TMyRecord2) >>>> geht 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: |
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:
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.
{M+}
TMyRecord1 = packed Record aInteger : integer; aString : String[100]; end; {M-} |
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.
![]() 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 .... |
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:
Gruß Hawkeye |
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ß. |
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? |
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 ![]() Gruß Hawkeye |
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:
Es werden also wirklich nur die Felder gespeichert, die finalisiert werden müssen.
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; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:01 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