Methode als Parameter



  • Hi,

    habe folgende Methode:

    void IPluginInterface::addFunction(std::string name, void* function);
    

    Das ganze soll ein Plugin System werden wo der späterer Plugin Schreiber eigene Methoden definieren/schreiben kann und diese dann mit addFunction bekannt geben soll.

    im Plugin cpp

    void PScreenSaver::initFunctions()
    {
     addFunction("Rectangle", Rectangle());
    }
    
    void PScreenSaver::Rectangle()
    {
     cout << "foobar" << endl;
    }
    

    als fehlermeldung bekomme ich folgendes

    screensaver.cpp:12: error: invalid use of void expression
    

    kann mir da jemand helfen?

    MFG
    xmarvel



  • Mach das doch einfach so

    void IPluginInterface::addFunction(void (*function) (void));
    void Rectangle (void);
    
    void PScreenSaver::initFunctions()
    {
     addFunction(Rectangle); //Ohne die Klammern, sonst ruft man die Funktion auf, und nimmt nicht ihre Adresse
    }
    

    So wie du es gemacht hast, rufst du in dem Aufruf von addFunction die Funktion Rectangle auf, und nimmst nicht ihre Adresse. Außerdem solltest du in dem Prototyp von IPluginInterface::addFunction keinen Zeiger auf void (also auf Beliebiges) definieren, sondern einen Zeiger auf einen Funktion, damit man die später auch ohne zu casten aufrufen kann, außerdem kann man sonst auch Funktionen übergeben, die Argumente übernehmen müssten, denen dann aber keine übergeben werden (oder noch schlimmer irgendwelche Adresen von irgendetwas, was dann als Funktion interpretiert wird).

    Was das mit den Namen der Funktion in IPluginInterface::addFunction soll, verstehe ich nicht wirklich, kanst du mir mal erklären, wozu du das benutzen willst?

    Felix



  • keinen Zeiger auf void (also auf Beliebiges) definieren, sondern einen Zeiger auf einen Funktion

    Afair kann man nicht einfach jede Funktion nach void* casten, auf deutsch, das dürfte gar nicht funktionieren.

    MfG SideWinder



  • Hast Recht, ich dachte immer, mit reinterpret_cast würde man Alles zu Allem gecastet kriegen, sorry mein Fehler!

    Felix



  • thx für die schnelle antwort.

    (oder noch schlimmer irgendwelche Adresen von irgendetwas, was dann als Funktion interpretiert wird).

    stimmt daran hab ich garnicht gedacht 👍

    Was das mit den Namen der Funktion in IPluginInterface::addFunction soll, verstehe ich nicht wirklich, kanst du mir mal erklären, wozu du das benutzen willst?

    Wenn Plugins geladen werden. Dann sollen entsprechende Einträge auf der Oberläche erscheinen der Name ist dann das was angezeigt wird.
    Hab das mit dem Namen erstmal rausgenommen und dann so verändert wie du geschrieben hast. Leider bekomm ich jetzt so ein Fehler:

    screensaver.cpp: In member function `virtual void PScreenSaver::initFunctions()':
    screensaver.cpp:12: error: no matching function for call to `PScreenSaver::addFunction(<unknown type>)'
    ../libinterface.h:31: error: candidates are: void IPluginInterface::addFunction(void (*)())
    

    MFG
    xmarvel



  • Hab jetzt verschiedene Parameter angegeben um mittels Trial & Error den Fehler zu finden 😉
    Jedesmal meckert er jedoch rum das im Parameter von addFunction; Rectangle ein unknown Typ sei (siehe im vorrigen post die Fehlermeldung).
    Hab aber kein Ansatz woran das liegen kann.

    Oder hab ich die Bemerkung von SideWinder falsch verstanden, dass das überhaupt nicht funktioniert? 😕

    MFG
    xmarvel



  • Hallo,

    wenn du den Code benutzt, den du geschrieben hast, dann uebergibst du hier eine
    Elementfunktion. Hierzu siehe hier:

    http://www.function-pointer.org/

    mfg
    v R



  • Hab mir den 2. Abschnitt komplett durchgelesen.
    Mein Code sieht jetzt so aus:

    //Plugin Interface .h
    class IPluginInterface
    {
    public:
    	void addFunction(void (*function)(void));
    };
    
    // Plugin .h
    class PScreenSaver : public IPluginInterface
    {
    public:
    	void Rectangle(void);
    	void initFunctions()
              {
                addFunction(&PScreenSaver::Rectangle);
              };
    };
    

    Jetzt kommt folgende Fehlermeldung:

    screensaver.h: In member function `virtual void PScreenSaver::initFunctions()':
    screensaver.h:14: error: no matching function for call to `PScreenSaver::addFunction(void (PScreenSaver::*)())'
    ../libinterface.h:31: error: candidates are: void IPluginInterface::addFunction(void (*)())
    

    Hab da jetzt auch wieder ein bissel rumgespielt. Da ist mir aufgefallen wenn ich die addFunction Methode in der selbe Klasse definiere wo ich es aufrufe und dann als Parameter (void (PScreenSaver::*function)(void)); nehme compiliert er es ohne zu murren.
    Da aber die Basisklasse nicht die Unterklassen kennt kann ich dort ja auch nicht PScreensaver::*function schreiben. Wie kann ich das lösen?

    MFG
    xmarvel



  • Wenn du einfache Funktionspointer verwenden willst, dann muß deine Klassenmethode "static" sein, d.h. intern ohne Klassenzeiger "this", also

    //Plugin Interface .h
    class IPluginInterface
    {
    public:
        void addFunction(void (*function)(void));
    };
    
    // Plugin .h
    class PScreenSaver : public IPluginInterface
    {
    public:
        static void Rectangle(void);
        void initFunctions()
              {
                addFunction(&PScreenSaver::Rectangle);
              };
    };
    

    Jedoch willst du wahrscheinlich in der Methode Rectangle auf Member von PScreenSaver zugreifen, so daß du evtl. Methodenzeiger verwenden solltest:

    //Plugin Interface .h
    class IPluginInterface
    {
    public:
        typedef void (IPluginInterface::*Method)(); // void entfernt
        void addMethod(Method f);
    };
    
    // Plugin .h
    class PScreenSaver : public IPluginInterface
    {
    public:
        void Rectangle();
        void initFunctions()
        {
          addMethod(static_cast<IPluginInterface::Method>(&PScreenSaver::Rectangle));
        }
    };
    

    Beim Hinzufügen wird jedoch ein "cast" auf den Basistyp verlangt, da Methodenzeiger leider nicht vererbbar sind.
    Nun kann Rectangle auch Member der Klasse PScreenSaver benutzen.

    Hier noch der Aufruf der Methode:

    void IPluginInterface::callMethod(Method f)
    {
       (this->*f)();
    }
    

    Ansonsten gibt es auch noch die SigC-Lib bzw. boost...



  • danke für eure Hilfe jetzt funktioniert es einwandfrei. 👍

    Nur als kleine Ergänzung für die den kleinen Code von Th auch gebrauchen können fehlt bei addMethod(static_castIPluginInterface::Method(PScreenSaver::Rectangle)); vor dem PScreenSaver ein &.

    MFG
    xmarvel



  • Schön, daß es funktioniert (habe auch den obigen Code korrigiert, hatte ihn aus dem Kopf hingeschrieben).


Anmelden zum Antworten