Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement a callback in C++?

Tags:

c++

callback

I want to implement a class in c++ that has a callback.

So I think I need a method that has 2 arguments:

  • the target object. (let's say *myObj)
  • the pointer to a member function of the target object. (so i can do *myObj->memberFunc(); )

The conditions are:

  • myObj can be from any class.

  • the member function that is gonna be the callback function is non-static.

I've been reading about this but it seems like I need to know the class of myObj before hand. But I am not sure how to do it. How can I handle this? Is this possible in C++?

This is something I have in mind but is surely incorrect.

class MyClassWithCallback{
public
    void *targetObj;
    void (*callback)(int number);
    void setCallback(void *myObj, void(*callbackPtr)(int number)){
        targetObj = myObj;
        callback = callbackPtr;
    };
    void callCallback(int a){
        (myObj)->ptr(a);
    };
};
class Target{
public
    int res;
    void doSomething(int a){//so something here. This is gonna be the callback function};        
};

int main(){
    Target myTarget;
    MyClassWithCallback myCaller;
    myCaller.setCallback((void *)&myTarget, &doSomething);

}

I appreciate any help.

Thank you.

UPDATE Most of you said Observing and Delegation, well that's i exactly what i am looking for, I am kind of a Objective-C/Cocoa minded guy. My current implementation is using interfaces with virtual functions. Is just I thought it would be "smarter" to just pass the object and a member function pointer (like boost!) instead of defining an Interface. But It seems that everybody agrees that Interfaces are the easiest way right? Boost seems to be a good idea, (assuming is installed)

like image 749
nacho4d Avatar asked Aug 01 '10 11:08

nacho4d


People also ask

How are callbacks implemented in C?

Callbacks in C are usually implemented using function pointers and an associated data pointer. You pass your function on_event() and data pointers to a framework function watch_events() (for example). When an event happens, your function is called with your data and some event-specific data.

How does callback function work in C?

A callback is any executable code that is passed as an argument to other code, which is expected to call back (execute) the argument at a given time [Source : Wiki]. In simple language, If a reference of a function is passed to another function as an argument to call it, then it will be called as a Callback function.

How do you implement a callback function?

A custom callback function can be created by using the callback keyword as the last parameter. It can then be invoked by calling the callback() function at the end of the function. The typeof operator is optionally used to check if the argument passed is actually a function. console.

Why do we use callback function in C?

The main advantage of using callbacks is that you can call a function that is defined in a higher software level from a lower software level subroutine. A callback can be used for notifications or signals.


1 Answers

The best solution, use boost::function with boost::bind, or if your compiler supports tr1/c++0x use std::tr1::function and std::tr1::bind.

So it becomes as simple as:

boost::function<void()> callback;
Target myTarget;
callback=boost::bind(&Target::doSomething,&myTarget);

callback(); // calls the function

And your set callback becomes:

class MyClassWithCallback{
public:
  void setCallback(boost::function<void()> const &cb)
  {
     callback_ = cb;
  }
  void call_it() { callback_(); }
private:
  boost::function<void()> callback_;
};

Otherwise you need to implement some abstract class

struct callback { 
 virtual void call() = 0;
 virtual ~callback() {}
};

struct TargetCallback {
 virtual void call() { ((*self).*member)()); }
 void (Target::*member)();
 Target *self;
 TargetCallback(void (Target::*m)(),Target *p) : 
       member(m),
       self(p)
 {}
};

And then use:

myCaller.setCallback(new TargetCallback(&Target::doSomething,&myTarget));

When your class get modified into:

class MyClassWithCallback{
public:
  void setCallback(callback *cb)
  {
     callback_.reset(cb);
  }
  void call_it() { callback_->call(); }
private:
  std::auto_ptr<callback> callback_;
};

And of course if the function you want to call does not change you may just implement some interface, i.e. derive Target from some abstract class with this call.

like image 115
Artyom Avatar answered Nov 15 '22 20:11

Artyom