C++ class member function callback

前端 未结 3 720
鱼传尺愫
鱼传尺愫 2020-12-03 13:07

I have the following problem. I have a function from an external library (which cannot be modified) like this:

void externalFunction(int n, void udf(double*)         


        
相关标签:
3条回答
  • 2020-12-03 13:29

    You can use Boost bind or TR1 bind (on recent compilers);;

    externalFunction(n, boost::bind(&myClass::classUDF, boost::ref(myClassObj)));
    

    Unfortunately, I lived in a pipe dream for the last 10 minutes. The only way forward is to call the target using some kind of a static wrapper function. The other answers have various neat (compiler-specific) tidbits on that, but here's the main trick:

    void externalFunction(int n, void (*udf)(double*) )
    { double x; udf(&x); }
    
    myClass myClassObj;
    void wrapper(double* d) { myClassObj.classUDF(d); }
    
    int main()
    {
        externalFunction(1, &wrapper);
    }
    

    std::function<>

    Store a bound function in a variable like this:

    std::function<void(double*)> stored = std::bind(&myClass::classUDF, boost::ref(myClassObj))
    

    (assuming C++0x support in compiler now. I'm sure Boost has a boost::function<> somewhere)

    Vanilla C++ pointers-to-member-function

    Without magic like that, you'd need pointer-to-memberfunction syntax:

    See also live on http://ideone.com/Ld7It

    Edit to clarify to the commenters, obviously this only works iff you have control over the definition of externalFunction. This is in direct response to the /broken/ snippet int the OP.

    struct myClass
    {
        void classUDF(double* a) { };
    };
    
    void externalFunction(int n, void (myClass::*udf)(double*) )
    {
        myClass myClassObj;
        double x;
        (myClassObj.*udf)(&x); 
    }
    
    int main()
    {
        externalFunction(1, &myClass::classUDF);
    }
    

    C++98 idiomatic solution

    // mem_fun_ref example
    #include <iostream>
    #include <functional>
    #include <vector>
    #include <algorithm>
    #include <string>
    
    int main () 
    {
        std::vector<std::string> numbers;
    
        // populate vector:
        numbers.push_back("one");
        numbers.push_back("two");
        numbers.push_back("three");
        numbers.push_back("four");
        numbers.push_back("five");
    
        std::vector <int> lengths (numbers.size());
    
        std::transform (numbers.begin(), numbers.end(), lengths.begin(), 
                    std::mem_fun_ref(&std::string::length));
    
        for (int i=0; i<5; i++) {
            std::cout << numbers[i] << " has " << lengths[i] << " letters.\n";
        }
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-03 13:44

    Here is how I do this, when MyClass is a singleton:

    void externalFunction(int n, void udf(double) );
    
    class MyClass
    {
    public:
       static MyClass* m_this;
       MyClass(){ m_this = this; }
       static void mycallback(double* x){ m_this->myrealcallback(x); }
       void myrealcallback(double* x);
    }
    
    int main()
    {
       MyClass myClass;
       externalFunction(0, MyClass::mycallback);
    }
    
    0 讨论(0)
  • 2020-12-03 13:53

    This is impossible to do - in c++, you must use either a free function, or a static member function, or (in c++11) a lambda without capture to get a function pointer.

    GCC allows you to create nested function which could do what you want, but only in C. It uses so-called trampolines to do that (basically small pieces of dynamically generated code). It would be possible to use this feature, but only if you split some of the code calling externalFunction to a separate C module.

    Another possibility would be generating code at runtime eg. using libjit.

    So if you're fine with non-reenrant function, create a global/static variable which will point to this and use it in your static function.

    class myClass
    {
    public:
        static myClass* callback_this;
        static void classUDF(double* a)
        {
            callback_this.realUDF(a);
        };
    };
    

    Its really horrible code, but I'm afraid you're out of luck with such a bad design as your externalFunction.

    0 讨论(0)
提交回复
热议问题