Wie kann man eine Funktion über den Funktionsnamen in Stringform aufrufen? TMethod???



  • Hallo,

    ich möchte dynamisch Funktionen anhand des Funktionsnamens, der als Ansistring vorliegt, aufrufen.
    Beispiel:

    AnsiString FuncName = "Testfunction"
    AufrufDerMethode(FuncName)
    

    Geht das mit TMethod und wenn wie ?

    Danke und Gruß
    Oliver



  • Hallo

    Das geht so einfach nicht, denn zur Laufzeit gibt es keine Funktionsnamen mehr. Du must eine Abwandlung des Factory Patterns anwenden.

    // Hier müßen alle aufrufbaren Funktionen registriert werden
    AufrufDerMethode(const AnsiString& name)
    {
      if (name == "Testfunction")
        Testfunction();
      else if (name == "...")
        ...();
    }
    
    // Anwendung
    AnsiString FuncName = "Testfunction";
    AufrufDerMethode(FuncName)
    

    bis bald
    akari



  • In Delphi geht folgendes:

    procedure TAufruf.ExecMethod(OnObject: TObject; MethodName: string) ;
    var
       Routine: TMethod;
       Exec: TExec;
    begin
       Routine.Data := Pointer(OnObject) ;
       Routine.Code := OnObject.MethodAddress(MethodName) ;
       if NOT Assigned(Routine.Code) then Exit;
       Exec := TExec(Routine) ;
       Exec;
    end;
    

    Ist das mit VCL nicht möglich ?



  • Hallo

    Im Builder 5 gibts es zwar TMethod, aber nicht TExec. Damit wird das wohl nicht im Builder umsetzbar sein, da es zu sehr auf Delphi-Internas aufsetzt.

    bis bald
    akari



  • Das habe ich leider auch gesehen.

    Ich hatte aber gehofft, wenn es TMethod gibt, dann gibt es auch eine Möglichkeit der dynamischen Funktionsaufrufe

    Die Verbindung von TMethod und TObject::MethodAddress ist wahrscheinlich die Lösung. Ich weiss nur nicht wie ich dann die Methode aufrufe

    TMethod myFunction;
    myFunction.Code = MethodAddress("Methode1");
    und nun ???
    


  • Hallo

    Genau das macht in Delphi ja TExec. Da es das im Builder nicht gibt wird das wohl nicht umsetzbar sein.
    Versuch dich lieber gleich im Stil von C++ und benutzt so ein gezeigtes plattformunabhängiges und standardkonformes Pattern.

    bis bald
    akari



  • Doch, auch mit dem C++Builder ist Reflection möglich. Dabei ist allerdings folgendes zu beachten:
    - es funktioniert nur mit von TObject abgeleiteten Klassen (was in Delphi auf alle Klassen zutrifft)
    - die aufzurufende Methode muß im __published-Abschnitt deklariert sein und die __fastcall-Parameterübergabekonvention verwenden

    So sollte es also klappen:

    // .hpp-Datei
    ...
    class TForm1 : public TForm
    {
    __published:
            TButton *Button1;
            void __fastcall Button1Click(TObject *Sender);
            void __fastcall doSomething (void);
            ...
    };
    ...
    
    // .cpp-Datei
    ...
    void ExecMethod (TObject* Object, AnsiString MethodName)
    {
            typedef void (__closure * __fastcall TExec) (void);
            TExec Exec;
            TMethod Routine;
    
            Routine.Data = Object;
            Routine.Code = Object->MethodAddress (MethodName);
            if (!Routine.Code)
                    return;
            Exec = *reinterpret_cast <TExec*> (&Routine); // ganz pöhse, da nicht typsicher, daher genau aufpassen, daß TExec die gleiche Parameterliste hat wie die aufzurufende Funktion
            Exec ();
    }
    ...
    
    void __fastcall TForm1::doSomething (void)
    {
            MessageBox (NULL, "MessageBox aus doSomething()", "...", MB_OK | MB_ICONINFORMATION);
    }
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
            ExecMethod (this, "doSomething");
    }
    

    akari schrieb:

    Damit wird das wohl nicht im Builder umsetzbar sein, da es zu sehr auf Delphi-Internas aufsetzt.

    Generell gilt: alles, was in Delphi geht, geht auch in C++Builder; Ausnahmen sind mir derzeit nicht bekannt. Die Delphi-spezifischen Spracheigenschaften wurden für die Unterstützung der VCL durch die speziellen Schlüsselwörter __classid, __closure, __fastcall, __property und __published im C++-Compiler verfügbar gemacht. Da der C++Builder neben dem VCL-Klassenmodell (in dem z.B. keine Mehrfachvererbung möglich ist) natürlich auch herkömmliche C++-Klassen unterstützt (in denen dafür auf Introspektion, Persistenz etc. verzichtet werden muß), ist C++Builder genau genommen sogar eine Obermenge von Delphi. Das ist auch das Grund dafür, daß C++Builder-Komponenten nicht in Delphi-Projekten verwendet werden können.

    akari schrieb:

    Versuch dich lieber gleich im Stil von C++ und benutzt so ein gezeigtes plattformunabhängiges und standardkonformes Pattern.

    Reflection in Standard-C++? Wie stellst du dir das vor?



  • Hallo

    Doch, auch mit dem C++Builder ist Reflection möglich. Dabei ist allerdings folgendes zu beachten:...

    Ich habe in meinem Builder 5 im Gegensatz zu TMethod TExec weder in Builder-Hilfe gefunden noch hat der Compiler TExec verstanden. Fehlt da noch ein include?

    Reflection in Standard-C++? Wie stellst du dir das vor?

    Nein eben nicht. Sondern in C++ übliche Design Pattern wie das Factory P. und Stategy P. benutzen.
    Denn ehrlich gesagt glaub ich trotz allem nicht das Borland seinem C++ Compiler echtes Reflection beigebracht hat. Sondern das wird effektiv auch nur eine Anwendung eines solchen Pattern sein, das unter der Haube läuft.

    bis bald
    akari



  • akari schrieb:

    Ich habe in meinem Builder 5 im Gegensatz zu TMethod TExec weder in Builder-Hilfe gefunden noch hat der Compiler TExec verstanden. Fehlt da noch ein include?

    Nein, das gibt es im BCB nicht; dort löst man es anders. Für Details siehe mein Beispiel oben - wo ich mir übrigens zur Übersichtlichkeit einen solchen Typ selbst definiert habe:

    typedef void (__closure * __fastcall TExec) (void);
    

    Viel mehr dürfte TExec in Delphi auch nicht sein.

    akari schrieb:

    Denn ehrlich gesagt glaub ich trotz allem nicht das Borland seinem C++ Compiler echtes Reflection beigebracht hat.

    Was soll das hier denn sonst sein? Zumindest meiner Definition nach (Reflection = die Fähigkeit eines Programmes, etwas über seine eigene Struktur herauszufinden) handelt es sich hierbei um Reflection, und das ist mit keinem mir bekannten in Standard-C++ realisierbarem Pattern so lösbar.
    Und wie gesagt - was Delphi kann, kann auch C++Builder 😉

    akari schrieb:

    Sondern das wird effektiv auch nur eine Anwendung eines solchen Pattern sein, das unter der Haube läuft.

    Hmm?
    Wie dem auch sei, wie Borland das implementiert hat, ist doch völlig irrelevant, oder?



  • Hallo

    Ah okay hab den typedef nicht ernst genommen. Ja dann machts Sinn.

    Echte Reflection würde bedeuten das es ein Teil der Sprache (C++) und des Compilers wäre.
    Ist es im Falle der gezeigten Methode aber nicht, das ist ein Teil des darauf aufbauenden Frameworks. Also nichts anderes als was ich auch mit einem MinGW-Compiler mit meinem eigenen Framework mittels der Pattern hinbekommen würde.

    bis bald
    akari



  • akari schrieb:

    Echte Reflection würde bedeuten das es ein Teil der Sprache (C++) und des Compilers wäre.
    Ist es im Falle der gezeigten Methode aber nicht, das ist ein Teil des darauf aufbauenden Frameworks.

    Doch, ist es. Die Dinge sind sowohl auf VCL- als auch auf Compilerebene implementiert (oder hältst du __published, __classid etc. für bibliotheksabhängig? Daß Namen und Typinformation zur Laufzeit verfügbar sind, liegt allein in der Verantwortung des Compilers). Sie sind nur eben auf von TObject abgeleitete Klassen beschränkt. Du kannst es auch so sehen: Reflection ist vorhanden, aber du hast die Option, darauf zu verzichten. Daß du überhaupt nicht von TObject abgeleitete Klassen erstellen kannst, ist nur in der notwendigen Kompatibilität zu Standard-C++ begründet - in Delphi geht das, wie ich bereits schrieb, nicht. Und das ist in anderen Sprachen, die Reflection unterstützen, wie z.B. Java und C#, ja auch nicht anders.

    akari schrieb:

    Also nichts anderes als was ich auch mit einem MinGW-Compiler mit meinem eigenen Framework mittels der Pattern hinbekommen würde.

    Viel Vergnügen dabei 🙂 Wenn du das schaffst, mußt du mir es unbedingt mal zeigen 😉



  • Vielen Dank audacia !!!

    Ich war auch erst daran verzweifelt, dass es TExec nicht gibt.
    Aber Deine Erklärung über __closure und Co. bringt Licht ins Dunkel.

    Gruß, Oliver


Anmelden zum Antworten