RTTI Zugriff auf Funktion

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
charlytango
Beiträge: 1184
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

RTTI Zugriff auf Funktion

Beitrag von charlytango »

Ich versuche auf eine Funktion eines Formulars zuzugreifen und den Rückgabewert oder einen Variablenwert auszuwerten ohne dass ich weiß ob das Formular diese Funktion bereitstellt.

Mit Variablen und Prozeduren klappt das hervorragend, bei Funktionen sperrt es sich etwas. Die KI hat sich da etwas zusammen halluziniert, liefert mir aber ein Mischmasch von Delphi und fpc

Kennt sich da vielleicht jmd aus ?
Lazarus 4.3, FPC 3.2.3

Code: Alles auswählen

uses
 ..typeinfo,rtti....

function CallBoolMethod(aForm: TObject; const MethodName: string; out
  ResultValue: Boolean): Boolean;
var
  ctx: TRttiContext;
  rttiType: TRttiType;
  method: TRttiMethod;
  retval: TValue;
begin
  Result := False;
  ResultValue := False;
  if aForm = nil then
    Exit;

  ctx := TRttiContext.Create;
  try
    rttiType := ctx.GetType(aForm.ClassType);
    method := rttiType.GetMethod(MethodName);

    if Assigned(method) and (method.ReturnType <> nil) and (method.ReturnType.Handle = TypeInfo(Boolean)) then
    begin
      retval := method.Invoke(aForm, []);
      if retval.IsBoolean then  //<<<Error: identifier idents no member "IsBoolean"
      begin
        ResultValue := retval.AsBoolean; 
        Result := True;
      end;
    end;
  finally
    ctx.Free;
  end;

end; 

PascalDragon
Beiträge: 992
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: RTTI Zugriff auf Funktion

Beitrag von PascalDragon »

Nachdem du eh schon den Rückgabetyp per ReturnType geprüft hast, brauchst du das nicht mehr mit dem IsBoolean machen (welches weder in Delphi noch in FPC existiert). Die Rtti Unit nutzt nämlich eh den ReturnType, um den zurückgegebenen TValue passend zu typisieren. Und falls doch was schief ging, dann gibt's ne Exception. 🤷‍♀️
In Delphi und FPC main kannst du TryCast<T>() verwenden.
FPC Compiler Entwickler

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2855
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: RTTI Zugriff auf Funktion

Beitrag von m.fuchs »

charlytango hat geschrieben: Mo 29. Sep 2025, 18:16 Die KI hat sich da etwas zusammen halluziniert, liefert mir aber ein Mischmasch von Delphi und fpc
Dann benutzt doch diesen Kram nicht, wenn es Unsinn ausliefert.
charlytango hat geschrieben: Mo 29. Sep 2025, 18:16

Code: Alles auswählen

uses
 ..typeinfo,rtti....
Du arbeitest mit der Unit Rtti, die als experimental gekennzeichnet ist, würde ich nicht machen. Eigentlich ist für RTTI ja immer noch die Unit TypInfo zuständig. Die kann allerdings nicht mit Methoden umgehen.
charlytango hat geschrieben: Mo 29. Sep 2025, 18:16 Ich versuche auf eine Funktion eines Formulars zuzugreifen und den Rückgabewert oder einen Variablenwert auszuwerten ohne dass ich weiß ob das Formular diese Funktion bereitstellt.
Was ist denn der Hintergrund des Ganzen? Vielleicht kann man das anders lösen...
0118999881999119725-3

Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

charlytango
Beiträge: 1184
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: RTTI Zugriff auf Funktion

Beitrag von charlytango »

m.fuchs hat geschrieben: Mo 29. Sep 2025, 21:22 Was ist denn der Hintergrund des Ganzen? Vielleicht kann man das anders lösen...
Es geht um ctGUI meine Tabbed GUI auf Basis JvTabBar.
Man kann derzeit beliebige TForms sehr leicht einhängen und die Standardfunktionen funktionieren.
Will der User nun zu einem anderen Tab wechseln, könnte das TForm wissen ob er das darf.
z.B kann eine im Formular befindliche Funktion CanChange false zurückgeben, falls er das nicht darf (zb weil Daten noch nicht gespeichert sind).

Klar kann man das über einen gemeinsamen Vorfahren aller TForms der Applikation lösen. Das wäre dann aber für diesen Fall zwingend.
Mit RTTI (Typeinfo) habe ich es bisher geschafft, dass ein gemeinsamer Vorfahre zwar bequem aber nicht zwingend nötig ist um eine einzelne Eigenschaft/Funktion im Tabmanagement abzubilden.
Wenn der Entwickler eine Eigenschaft braucht, baut er einfach eine bestimmte public property in sein Formular und schon klappt es, weil die GUI diese Eigenschaft per Typeinfo ausliest und sich nicht auf den Vorfahren kapriziert.

Nun wollte ich das auch für eine Funktion machen, die einen boolean zurückgibt.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2855
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: RTTI Zugriff auf Funktion

Beitrag von m.fuchs »

Es klingt für mich, als würde es nach einem Einsatz von Interfaces schreien, anstelle von RTTI.
0118999881999119725-3

Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1694
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: RTTI Zugriff auf Funktion

Beitrag von fliegermichl »

Hmm,

ich habe mal versucht, das nach zu bauen aber bekomme schon bei

Code: Alles auswählen

 method := rttiType.GetMethod(MethodName);
nil in method zurück obwohl das übergebene Formular diese Methode bereitstellt. Wie kann man denn rttiType.GetMethod dann sinnvoll verwenden?

charlytango
Beiträge: 1184
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: RTTI Zugriff auf Funktion

Beitrag von charlytango »

m.fuchs hat geschrieben: Di 30. Sep 2025, 00:37 Es klingt für mich, als würde es nach einem Einsatz von Interfaces schreien, anstelle von RTTI.
Das ist mir leider trotz langer Jahre ein Buch mit sieben Siegeln. Interessanterweise lerne ich hier bei euch mehr als in vielen Jahren davor:-)

Dieses Interface müsste dann wohl in der "einzuklebenden" TForm bzw in dessen Vorfahren existieren?

Falls ja, wäre die Hürde ctGUI zu nutzen größer, weil komplexer einzubauen als eine simple public function.

charlytango
Beiträge: 1184
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: RTTI Zugriff auf Funktion

Beitrag von charlytango »

fliegermichl hat geschrieben: Di 30. Sep 2025, 04:19 Hmm,

ich habe mal versucht, das nach zu bauen aber bekomme schon bei

Code: Alles auswählen

 method := rttiType.GetMethod(MethodName);
nil in method zurück obwohl das übergebene Formular diese Methode bereitstellt. Wie kann man denn rttiType.GetMethod dann sinnvoll verwenden?
Diese Prozedur funktioniert (nur mit TypeInfo, dazu braucht es kein rtti). Sie ruft allerdings nur eine Eventprozedur auf ohne einen Rückgabewert auszuwerten.
Vielleicht hilft es beim Überlegen

Code: Alles auswählen

uses ..... typeinfo;

{Call Notify Event if it exists only}
procedure CallNotfyEvent(aForm: TForm; sPropertyName: string);
var
  PropInfo: PPropInfo;
  Method: TMethod;
  EventProc: TNotifyEvent;
begin
  if not Assigned(aForm) then
    Exit;

  {$ifdef LAZLOGGER}
    Debugln('****CallNotfyEvent**** -> Calling NotfyEvent ',sPropertyName,' of form ', aForm.Name );
    DebuglnEnter('');
  {$endif}

  // RTTI verwenden, um die Eigenschaft sPropertyName zu finden
  PropInfo := GetPropInfo(aForm, sPropertyName);
  if PropInfo <> nil then
  begin
    Method := GetMethodProp(aForm, PropInfo); // Methodenzeiger der Eventprozedur holen  -- Get method pointer
    if Assigned(Method.Code) then
    begin
      EventProc := TNotifyEvent(Method);      // Methodenzeiger in den korrekten Typ casten -- cast method pointer to TNotifyEvent

      {$ifdef LAZLOGGER}
        Debugln('****CallNotfyEvent**** -> vor aufruf ');
        DebuglnEnter('');
      {$endif}

      EventProc(aForm);                       // NotifyEvent aufrufen  -- Call TNotifyEvent of the form
      //EventProc(nil);
    end;
  end
  {$ifdef LAZLOGGER}
    else
      Debugln('                NotfyEvent ',sPropertyName,' of form ', aForm.Name , ' not found');
  DebuglnExit('');
  {$endif}
  ;

end;

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1694
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: RTTI Zugriff auf Funktion

Beitrag von fliegermichl »

charlytango hat geschrieben: Di 30. Sep 2025, 10:16
Diese Prozedur funktioniert (nur mit TypeInfo, dazu braucht es kein rtti). Sie ruft allerdings nur eine Eventprozedur auf ohne einen Rückgabewert auszuwerten.
Vielleicht hilft es beim Überlegen
Funktioniert bei mir nicht. Ich habe eine unit2 mit einem TForm2, welches eine public procedure Hallo(Sender : TObject) definiert.

Der Aufruf von

Code: Alles auswählen

  PropInfo := GetPropInfo(Form2, 'hallo');
Liefert nil zurück!?

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2855
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: RTTI Zugriff auf Funktion

Beitrag von m.fuchs »

charlytango hat geschrieben: Di 30. Sep 2025, 10:11
m.fuchs hat geschrieben: Di 30. Sep 2025, 00:37 Es klingt für mich, als würde es nach einem Einsatz von Interfaces schreien, anstelle von RTTI.
Das ist mir leider trotz langer Jahre ein Buch mit sieben Siegeln. Interessanterweise lerne ich hier bei euch mehr als in vielen Jahren davor:-)
Dieses Interface müsste dann wohl in der "einzuklebenden" TForm bzw in dessen Vorfahren existieren?
Ich hab mal ein Beispiel zusammen geklöppelt. Schau dir das den Anhang mal an.
charlytango hat geschrieben: Di 30. Sep 2025, 10:11 Falls ja, wäre die Hürde ctGUI zu nutzen größer, weil komplexer einzubauen als eine simple public function.
Naja, man muss halt zusätzlich noch das Interface einbinden in das Form - das ist dann ein Wort mehr was man schreiben muss.
Dateianhänge
FormsAndInterfaces.zip
(72.19 KiB) 196-mal heruntergeladen
0118999881999119725-3

Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

charlytango
Beiträge: 1184
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: RTTI Zugriff auf Funktion

Beitrag von charlytango »

herzlichen Dank,ich sehe es mir mal an.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1694
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: RTTI Zugriff auf Funktion

Beitrag von fliegermichl »

fliegermichl hat geschrieben: Di 30. Sep 2025, 13:25
charlytango hat geschrieben: Di 30. Sep 2025, 10:16
Diese Prozedur funktioniert (nur mit TypeInfo, dazu braucht es kein rtti). Sie ruft allerdings nur eine Eventprozedur auf ohne einen Rückgabewert auszuwerten.
Vielleicht hilft es beim Überlegen
Funktioniert bei mir nicht. Ich habe eine unit2 mit einem TForm2, welches eine public procedure Hallo(Sender : TObject) definiert.

Der Aufruf von

Code: Alles auswählen

  PropInfo := GetPropInfo(Form2, 'hallo');
Liefert nil zurück!?
Ist klar. GetPropInfo kann nur Informationen zu Properties liefern.

Wenn man aber procedure DoHallo als published deklariert, dann kann man über aForm.MethodAddress einen Zeiger auf die Methode erlangen.
Wie man damit dann weiter umgeht, muss ich erst noch rausfinden.

Benutzeravatar
fliegermichl
Lazarusforum e. V.
Beiträge: 1694
Registriert: Do 9. Jun 2011, 09:42
OS, Lazarus, FPC: Lazarus Fixes FPC Stable
CPU-Target: 32/64Bit
Wohnort: Echzell

Re: RTTI Zugriff auf Funktion

Beitrag von fliegermichl »

So geht's

Code: Alles auswählen

type
  TBoolMethod = function : boolean of Object;
var
  p : Pointer;
  BoolMethod : TBoolMethod absolute p;

procedure TForm1.Button1Click(Sender: TObject);
var b : boolean;
begin
  p := Form2.MethodAddress('BoolHallo');
  TMethod(BoolMethod).code:= p;
  TMethod(BoolMethod).data:=form2;
  b := BoolMethod();
  if (b) then
    showmessage('ja')
  else
    showmessage('nein');
end;

charlytango
Beiträge: 1184
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: RTTI Zugriff auf Funktion

Beitrag von charlytango »

danke, wird etwas dauern bis ich das checken kann

charlytango
Beiträge: 1184
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: RTTI Zugriff auf Funktion

Beitrag von charlytango »

fliegermichl hat geschrieben: Mi 1. Okt 2025, 12:57 So geht's
hab ich mal ausprobiert und es klappt tatsächlich -- solange der Rückgabewert der gesuchten Fungtion (Form2.MethodAddress('BoolHallo');) true ist -- wird sie auf false gesetzt, kommen Speicherverletzungen

Antworten