Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   GetPropList weigert sich (https://www.delphipraxis.net/165651-getproplist-weigert-sich.html)

Medium 10. Jan 2012 11:43

Delphi-Version: 2007

GetPropList weigert sich
 
Mahlzeit!

Vorab: Delphi 2007

Ich bräuchte eine Liste aller Properties von einer Instanz, wozu sich GetPropList() ja prima eignen sollte. Ich habe auch zig Codeschnipsel gefunden, die das scheinbar völlig problemlos verwenden, bei mir springt leider der Compiler raus.
Delphi-Quellcode:
function TMyObject.GetPropTexts(aObj: TMyObject): String;
var
  list: TPropList;
  propCount, i: Integer;
begin
  propCount := GetPropList(aObj, @list); // "Es gibt keine überladene Version von 'GetPropList', die man mit diesen Argumenten aufrufen kann"
  for i := 0 to propCount do
  begin
    ...
Auch probiert, mit dem selben Ergebnis:
Delphi-Quellcode:
propCount := GetPropList(PTypeInfo(aObj.ClassInfo), @list);
und
Delphi-Quellcode:
propCount := GetPropList(aObj, PPropList(@list));
Wenn ich statt des Arrays gleich einen Pointer nehme:
Delphi-Quellcode:
function TMyObject.GetPropTexts(aObj: TMyObject): String;
var
  pList: PPropList;
  propCount, i: Integer;
begin
  propCount := GetPropList(aObj, pList);
  ...
Dann kompiliert das ganze zwar, läuft aber auf eine AV an Adresse $00000001. Ich hab nachgesehen: GetPropInfo alloziert die Liste via GetMem() selbst. Sollte also an sich auch gehen, und habe ich auch in manchen Quellfetzen im Netz gesehen!

Was mache ich hier verkehrt?

Besten Dank schon mal!


\\Edit: Mehr Infos.
Komisches passiert in dieser Funktion, die die Überladung mit PPropList-Parameter (also die kompilierende) aufruft:
Delphi-Quellcode:
function GetTypeData(TypeInfo: PTypeInfo): PTypeData; assembler;
asm
        { ->   EAX Pointer to type info }
        { <-    EAX Pointer to type data }
        {       it's really just to skip the kind and the name }
        XOR    EDX,EDX
        MOV    DL,[EAX].TTypeInfo.Name.Byte[0]
        LEA    EAX,[EAX].TTypeInfo.Name[EDX+1]
end;
In der 2. Zeile springt der Debugger auf einmal in die Classes.pas, und zwar in die Methode TThreadList.LockList. Was zum Henker will der DA!? Da jodelt der 2 Mal durch, und hängt dann was länger in der StdWndProc rum, und dann gibts irgendwann die o.g. AV. Wattatten?

Neutral General 10. Jan 2012 11:53

AW: GetPropList weigert sich
 
Hallo,

Also bei mir funktioniert das hier ohne Probleme:

Delphi-Quellcode:
uses
  TypInfo;

procedure TForm1.FormCreate(Sender: TObject);
var plist: PPropList;
    i, n: Integer;
begin
  n := GetPropList(Self,plist);
  try
    for i := 0 to n-1 do
      Memo1.Lines.Add(plist^[i]^.Name);
  finally
    FreeMem(plist);
  end;
end;
Wie sieht denn die Klasse des Objekts aus, dass du übergibst?
Sind generische Properties drin?

Bummi 10. Jan 2012 11:53

AW: GetPropList weigert sich
 
http://www.swissdelphicenter.ch/torr...de.php?id=1084

Medium 10. Jan 2012 12:02

AW: GetPropList weigert sich
 
Danke euch! Beide bringen mich nach wie vor zu oben genanner AV. Folglich ist entweder mein Delphi matsche, oder es ist damit überfordert die RTTI in einer Win7 VM zu bemühen. Ich starte hier erstmal alles neu, und dann mal sehen. Sowas blödes :(

Medium 10. Jan 2012 12:39

AW: GetPropList weigert sich
 
Liste der Anhänge anzeigen (Anzahl: 1)
Leider auch nach Neustart keine Besserung, und das Kompilat zeigt auch auf einem "echten" PC die AV. Die Klasse ist völlig unspektakulär, da ich gerade genau am Anfang bin eine Idee umzusetzen.

Delphi-Quellcode:
  TTestDrawObject = class
  private
    FWidth: Single;
    FHeight: Single;
    FTop: Single;
    FLeft: Single;
    procedure SetHeight(const Value: Single);
    procedure SetWidth(const Value: Single);
    function GetIntHeight: Integer;
    function GetIntWidth: Integer;
  protected
    procedure Paint; virtual;
    function PropText(aPropName: String; aValue: Integer): String; overload;
    function PropText(aPropName: String; aValue: Single): String; overload;
    function PropText(aPropName: String; aValue: String): String; overload;
    function PropText(aPropName: String; aValue: TTestDrawObject): String; overload;
  public
    property Left: Single read FLeft write FLeft;
    property Top: Single read FTop write FTop;
    property Width: Single read FWidth write SetWidth;
    property Height: Single read FHeight write SetHeight;
    property IntWidth: Integer read GetIntWidth;
    property IntHeight: Integer read GetIntHeight;
    procedure SetSize(aWidth, aHeight: Single);
    function ToText: String;
    constructor Create;
    destructor Destroy; override;
  end;
Alle Getter bzw. Setter machen nichts als die Felder zurückgeben (bzw. vorher aufzurunden bei den GetInt*) oder zu setzen - da soll später mehr rein. die PropText() Methoden sind auch leere Rümpfe bis auf den letzten, welcher eben die problematische Funktion beinhaltet. Aufgerufen wird diese von "ToText" mit den Parametern (self.ClassName, self).

PropText() ist bislang auch eher wenig imposant:
Delphi-Quellcode:
function TMyDrawObject.PropText(aPropName: String; aValue: TMyDrawObject): String;
var
  List: PPropList;
  size, propCount, i: Integer;
begin
  propCount := GetPropList(aValue.ClassInfo, tkAny, nil);
  size := propCount * SizeOf(Pointer);
  GetMem(List, size);
  propCount := GetPropList(aValue.ClassInfo, tkAny, List); // AV nach dieser Zeile
  result := '';
end;
Das ganze soll eine kleine Serialisierung von Zeichenobjekten werden. Als Eigenbau, weil ich (viel) später mal ein paar Speziellere Dinge brauchen werde, so dass es mir wesentlich einfacher erschien diese an sich ja einfach Funktion fix selbst hinzutippern, als mich erst lange in Fremdlösungen eindenken zu müssen um sie anzupassen, und ich das Format gerne möglichst schlank halten will, weil davorn nachher einiges übers Netzwerk flitzen soll. "fix selbst hintippern" - denkste :D

Bin keinen Schritt weiter :( Mich irritiert der Sprung in die TThreadList-Methode total. Mein Testprogramm tut aber auch nichts böses: Ein Button, ein Memo, ein TMyDrawObject wird erzeugt, und Memo1.Lines.Add(obj.ToText); aufgerufen. Ansonsten ist das ein frisches Projekt.


\\Edit: TMyDrawObject auf nur eine Property und eine nicht-überladene PropText()-Methode reduziert, komplett neues Testprojekt mit Button+Memo gemacht, und der Fehler bleibt. So langsam werd ich knüsselich :?

\\Edit2: Ich hab mal ein Testprojekt gebaut. Wäre prima, wenn das mal wer testen würde! Am liebsten natürlich auch mit D2007, aber auch generell würd ich's gern wissen. Ich habe mein Kompilat mit drin gelassen - wäre ja nicht unspannend, ob das auf einem anderen PC eventuell tut!

Bummi 10. Jan 2012 15:04

AW: GetPropList weigert sich
 
Zitat:

Ermittelt eine Liste mit den Komponenteneigenschaften
Du sitzt aber direkt auf Class

Medium 10. Jan 2012 15:48

AW: GetPropList weigert sich
 
Die 3. Überladung von GetPropList hat explizit "TObject" als Parameter, kein TComponent, kein TPersistent, kein nix. Die Hilfe erwähnt auch nirgends, dass da doch kein TObject übergeben werden darf, und somit würde ich eigentlich annehmen, dass das so okay ist. Ist das am Ende wieder nur eine Verwirrung dank genialer Dokumentation (und irreführender Parameterliste) seitens Emba?
Was wäre denn die "kleinste" Basisklasse, für die ich GetPropInfo() benutzen kann?

guinnes 10. Jan 2012 15:57

AW: GetPropList weigert sich
 
Gehen bei den "Alten" Delphi's nicht nur Published-Properties ?

Medium 10. Jan 2012 16:08

AW: GetPropList weigert sich
 
Das habe ich mittlerweile auch probiert, weil mir so etwas im Hinterkopf war. Zwar hätte dann der Rückgabewert von GetPropList() einfach nur 0 sein dürfen, und keine AV auslösen, aber einen Versuch war es dennoch wert. Leider mit dem selben Ergebnis: AV :(

Mag keiner fix mein kleines Testprojekt von weiter oben mal anfahren? Ich würde gerne klären, ob es eventuell an meinem Delphi bzw. sonstigem Setup liegt, oder ich wirklich ein tiefgreifendes Verständnisproblem hier habe :)

guinnes 10. Jan 2012 16:12

AW: GetPropList weigert sich
 
Zitat:

Zitat von Medium (Beitrag 1145231)
Das habe ich mittlerweile auch probiert, weil mir so etwas im Hinterkopf war. Zwar hätte dann der Rückgabewert von GetPropList() einfach nur 0 sein dürfen, und keine AV auslösen, aber einen Versuch war es dennoch wert. Leider mit dem selben Ergebnis: AV :(

Hast du dabei auch von TPersistent abgeleitet ? Published macht darunter keinen Sinn

implementation 10. Jan 2012 16:44

AW: GetPropList weigert sich
 
Habe das fertige Kompilat von dem Testprogramm mal hier bei mir über Wine ausgeführt. Auch hier eine AV auf $00000001.
Delphi habe ich nicht, aber ich habe es mal mit dem FPC gegen die LCL kompiliert, das läuft problemlos.

einbeliebigername 10. Jan 2012 18:45

AW: GetPropList weigert sich
 
Hallo,

Zitat:

Zitat von Medium (Beitrag 1145228)
Ist das am Ende wieder nur eine Verwirrung dank genialer Dokumentation (und irreführender Parameterliste) seitens Emba?
Was wäre denn die "kleinste" Basisklasse, für die ich GetPropInfo() benutzen kann?

Na ja der Parametertyp ist schon von Emba richtig gewählt. Also entweder du Erbst von TPersistent oder aber du setzt um deine Klasse ein

Delphi-Quellcode:
{$M+}

{$M-}
herum. Wenn du ohne diesen Schalter anzumachen von einer Klasse erbst, bei deren Definition dieser nicht an war und einen Published-Teil hast, wirft Delphi eine Warnung. In der Hilfe zu der Warnung ist glaube ich das Thema auch erklärt.

Einbeliebigername.

Edit: Was vergessen.

Medium 10. Jan 2012 22:54

AW: GetPropList weigert sich
 
Diese Warnung hatte ich nicht :gruebel: (Weiss ich recht genau, da ich mit einem Kompilat idR erst zufrieden bin, wenn 0 Fehler, 0 Warnungen und 0 Hinweise nach Erstellen da stehen.)
Ich werd das morgen nochmals testen, da ich wegen RegisterClass() (wegen FindClass()) nun ohnehin auf TPersistent aufsetze. Ein dumpfes Gefühl sagt mir, dass das dennoch in diesem seltsamen "Hüpfer" enden wird, aber man soll ja optimistisch sein! Danke euch schon mal!

einbeliebigername 11. Jan 2012 01:10

AW: GetPropList weigert sich
 
Hallo,

Zitat:

Zitat von Medium (Beitrag 1145299)
Diese Warnung hatte ich nicht :gruebel: (Weiss ich recht genau, da ich mit einem Kompilat idR erst zufrieden bin, wenn 0 Fehler, 0 Warnungen und 0 Hinweise nach Erstellen da stehen.)

Aber als du es mit published probiert hast, muss es eine Warnung gegeben haben. Ansonsten sehr löblich.

Ich habe noch mal mein Rad2007 angeworfen und ein Test-Programm geschrieben. Beim Schreiben ist mir dann auch noch ein Fehler in deinem Code aufgefallen. In der Zeile
Delphi-Quellcode:
for i := 0 to propCount do
fehlt das
Delphi-Quellcode:
-1
.

Folgender Sourcecode steht zur Diskussion.
Delphi-Quellcode:
program RttiProject1;

{$APPTYPE CONSOLE}

uses
  Classes,
  TypInfo;

type
  //{$M+} // Variante 1
  TTest= class//(TPersistent) // Variante 2
  strict private
    fTest: Integer;
  published
    property Test: Integer read fTest write fTest;
  end;
  //{$M-} 

var
  Obj: TTest;
  List: PPropList;
  Count, I: Integer;

begin
  Obj:= TTest.Create;
  try
    Count := GetPropList(Obj, List);
    for I := 0 to Count- 1 do
      Writeln(List[I].Name);
  finally
    Obj.Free;
  end;
  Writeln('Press Enter');
  Readln;
end.
Wenn man den so kompiliert, mit dem Auskommentierten, gibt es folgende Warnung:
Code:
[DCC Warnung] RttiProject1.dpr(14): W1055 PUBLISHED verursachte, dass RTTI ($M+) zu Typ 'TTest' hinzugefügt wurde
Man sollte sich den Text auch mal durch lesen. Denn eigentlich ist das genau das was du willst. Trotzdem funktioniert das Programm nicht wie gewollt. Es bleibt bei
Delphi-Quellcode:
GetPropList
hängen (Nach 10 Sekunden hatte ich keine Lust mehr zu warten). Erst wenn man Variante 1 oder 2 ein kommentiert geht es wie gewollt. Wenn man ohne Variante 1 und 2 auf das published verzichtet hängt es auch. Wer lügt da nun. Die Warnung oder die Funktion. Ich Tippe auf den Compiler, der hat immer Schuld.

Einbeliebigername.

Medium 11. Jan 2012 09:58

AW: GetPropList weigert sich
 
Da brat mir einen einen Storch. Du hast von vorne bis hinten Recht, auch mit der Warnung. :oops: Manchmal ist man ja schon etwas Blindfischig. Mit TPersistent als Vorfahr geht alles wie am Schnürchen, und da ich es ohnehin brauche, ist meine Welt nun wieder völlig genesen :) Besten Dank an alle! (FPC scheint da dann wohl etwas weniger stringent zu sein.)

implementation 11. Jan 2012 14:43

AW: GetPropList weigert sich
 
Zitat:

Zitat von Medium (Beitrag 1145328)
(FPC scheint da dann wohl etwas weniger stringent zu sein.)

Der macht da keine Probleme. Man kann TObject-Nachfahren Published-Properties geben und sie auch wieder abfragen. Es hat mich jetzt gewundert, dass das in Delphi nur ab TPersistent geht. Was ist denn der Grund dazu?

Neutral General 11. Jan 2012 14:44

AW: GetPropList weigert sich
 
Es geht (bei mir) auch bei Nachfahren von TObject, wenn man {$M+} für diese Klasse definiert.

implementation 11. Jan 2012 14:47

AW: GetPropList weigert sich
 
Zitat:

Zitat von Neutral General (Beitrag 1145411)
Es geht (bei mir) auch bei Nachfahren von TObject, wenn man {$M+} für diese Klasse definiert.

Wofür steht denn $M+?

Medium 11. Jan 2012 16:03

AW: GetPropList weigert sich
 
Ich würde schätzen, dass dann der Compiler eine Hand voll mehr RTTI-Infos für diese Klasse erzeugt. Da sich der Schalter auch auf alle Ableitungen auswirkt, und TPersistent die "jüngste" VCL Klasse ist, die den Schalter setzt, "erbe" ich quasi davon mit. Ich nehme einfach mal an, dass FPC grunsätzlich die Infos macht, oder der Schalter per Default projektweit an ist.
Ein einfaches {$M+} hätte mir hier denke ich geholfen, da ich aber ohnehin RegisterClass() brauche, und das als Parameter eine TPersistentClass will, sind das quasi zwei Fliegen mit einer Klappe.

Komisch ist, dass die Warnmeldung bei published-Properties ohne {$M+} lautet:
Zitat:

[DCC Warnung] Unit1.pas(33): W1055 PUBLISHED verursachte, dass RTTI ($M+) zu Typ 'Txxx' hinzugefügt wurde
Ich aber dennoch bei Verwendung von GetPropList darauf im Nirvana lande. Es liest sich ja so, als würde der Schalter automatisch gesetzt, aber soooo ganz äquivalent kann das dann ja nicht sein :?

ScharfeMietze 5. Jun 2019 14:13

AW: GetPropList weigert sich
 
Auch wenn das Thema alt ist, hat es bei mir geholfen es Local zu deklarieren und schon verschwand bei mir die Meldung vom TE die ich auch hatte
Delphi-Quellcode:
ar plist: PPropList;
    i, n: Integer;
    LBotCommands2: TBotCommands2;
begin
LBotCommands2:= TBotCommands2.Create(Self);
  try
    n := GetPropList(LBotCommands2,plist);
    try
      for i := 0 to n-1 do
        mmo1.Lines.Add(plist^[i]^.Name);
    finally
      FreeMem(plist);
      end;
  finally
   LBotCommands2.Free;
  end;
end;
Gruß

peterbelow 5. Jun 2019 18:52

AW: GetPropList weigert sich
 
Zitat:

Zitat von Medium (Beitrag 1145185)
Mahlzeit!

Vorab: Delphi 2007

Ich bräuchte eine Liste aller Properties von einer Instanz, wozu sich GetPropList() ja prima eignen sollte. Ich habe auch zig Codeschnipsel gefunden, die das scheinbar völlig problemlos verwenden, bei mir springt leider der Compiler raus.
Delphi-Quellcode:
function TMyObject.GetPropTexts(aObj: TMyObject): String;
var
  pList: PPropList;
  propCount, i: Integer;
begin
  propCount := GetPropList(aObj, pList);
  ...
Dann kompiliert das ganze zwar, läuft aber auf eine AV an Adresse $00000001. Ich hab nachgesehen: GetPropInfo alloziert die Liste via GetMem() selbst. Sollte also an sich auch gehen, und habe ich auch in manchen Quellfetzen im Netz gesehen!

Was mache ich hier verkehrt?

Erstmal:hat deine Klasse überhaupt published Properties? Nur für die wird RTTI erzeugt. Wenn das also nicht der Fall ist sollte propCount 0 zurückliefern und pList ist dann undefiniert.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:43 Uhr.

Powered by vBulletin® Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2020 by Daniel R. Wolf