Call a function or method dynamically



  • Is there a way to call a function dynamically ? I mean, passing the name of the method or function as a string to call it? I have my doubts about this, specifically, because I believe in a compiled lenguage this can't be done...thank you guys



  • Technically, function and method are the same thing. And no, you cannot do what you describe.

    You can use function pointers thou, you can "call" a function pointer and have executed any function it points too, as long as you stick to the same signature.



  • Yeah, That's what I thought...thank you very muchhh



  • In fact, you can.

    1. If you have many functions exported in the shared library, you can load the library, and resolve the functions by their name. After that, you get a function pointer.

    2. If you are using Qt, you can call a method function by their name with the help of meta-object.
      @
      QMetaObject::invokeMethod()
      @



  • hey, 1+1=2 , I have read about that , but I in the descriptions says
    "Invokes the member (a signal or a slot name) on the object obj."
    so, I thought it can be just used to call a signal or slot, of course, I could declare any of my functions as a slot but I don't know, I thought it wasn't the most convenient. xD I'll try with that



  • If the set of functions you may want to call is known then, yes, you can do this in C++ with what is called a Factory pattern. Very standard stuff.



  • 1+2^^Yes, some vendor specific solutions exist, the C++ standard itself does not support this.

    @Dead - I doubt resolving strings with "if equal" and launching per-determined functions is the intent of the OP.

    EDIT: A clarification:

    In C++, variable, object and function names are irrelevant during runtime, identifies only exist for the convenience of us humans, the compiler converts identifiers to memory addresses and offsets. In this regard, you simply cannot use a string during runtime as an identifier. On the other hand, you can still resolve strings to memory locations of either static or dynamic functions and call them using a function pointer mechanism.



  • Using invoke method is the Qt solution, but it works only for slots:
    @
    #include <QMetaobject>
    #include <QObject>
    #include <iostream>

    class MyClass : public QObject
    {
    Q_OBJECT
    public:
    MyClass(QObject *parent) : QObject(parent) {}
    public slots:
    void someMethod() {
    std::cout << "someMethod was called \n";
    }
    };

    int main(int argc, char *argv[])
    {
    MyClass obj(0);
    QMetaObject::invokeMethod(&obj, "someMethod", Qt::DirectConnection);
    return 0;
    }

    #include "main.moc"
    @



  • ^^ you can use a similar approach for plain functions, just have to write some boiler plate instead of the MOC, just register the strings and appropriate functions in let's say a map (that's probably how the MOC does it too) and have another function that resolves the string to the appropriate memory address and call it...

    All those approaches still require the code to be designed with that intent to begin with, you have to index all the functions you'd want to call with all the appropriate strings. As for just just calling a function using a string in the same manner identifiers are used in the source code - that is impossible.



  • ;-)

    [quote author="leninbooter" date="1338835994"]hey, 1+1=2 , I have read about that , but I in the descriptions says
    "Invokes the member (a signal or a slot name) on the object obj."
    so, I thought it can be just used to call a signal or slot, of course, I could declare any of my functions as a slot but I don't know, I thought it wasn't the most convenient. xD I'll try with that[/quote]

    It's not required to be signal or slot.

    @
    Q_INVOKABLE

    Apply this macro to definitions of member functions to allow them to be invoked via the meta-object system. The macro is written before the return type, as shown in the following example:
    @



  • A quick example of how you can achieve similar functionality without relying on the meta object API, it is quite simple really:

    @#include <QMap>
    #include <QTextStream>
    #include <QString>

    QTextStream cout(stdout);
    typedef void (*foo)(); // define foo to be pointer to void function()
    QMap<QString, foo> map; // map of strings and foos

    // a new basic methods
    void one(){
    cout << "Function one" << endl;
    }

    void two(){
    cout << "Function two" << endl;
    }

    void three(){
    cout << "Function three" << endl;
    }

    //wrapper calling function
    void callMethod(const QString &name){
    foo myFoo = map.value(name); //assign new foo to value in the map
    if (myFoo) myFoo(); //call it if not 0
    }

    int main()
    {
    //index functions with names
    map.insert("one", one);
    map.insert("two", two);
    map.insert("three", three);

    //call using strings
    callMethod("one");
    callMethod("two");
    callMethod("three");
    callMethod("blahblah"); // nothing happens
    

    }@



  • You should use Qt's meta-object implementation unless you have very specific reasons not to do so (for example when your class must not derive from QObject). It is well tested code, works as expected in multi-threaded environments, type-safe and allows for passing arguments and recieving return values.

    Just derive your class from QObject (if it not already does directly or indirectly) and declare the desired method as slot or Q_INVOKABLE and then use QMetaObject::invokeMethod().



  • Yep, my example was intended to be more of ... an example of how things work, not THE best, safest and most flexible way to do it. My rule of thumb - never just use something, assuming it will magically work, even if going for a complete and more advanced solution have at least basic idea how it works.



  • This made me think about the "Callback approach":http://en.wikipedia.org/wiki/Callback_(computer_programming) . Out of the box it won't work with just strings though.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.