0

I have simple UI class and I need to send UI element instance to callbacks for each element, so I can (much like in javascript) manipulate element which called the callback.
This requires to send instance of this to the function registered as callback. How do I do that?
Current state:

class Opencv_Button {
private:
    bool (*callback)(void*);                 //Callback WITHOUT the current button isntance
    //bool(*callback)(Opencv_Button, void*); //this is CALLBACK I WANT instead
    void* callback_param;                    //parameter set by user
    bool state;
    bool mouse(int, int, int);
public:
    Opencv_Button(int, int, int, int);
    void setCallback(bool(*)(void*), void*);
    //void setCallback(bool(*)(Opencv_Button, void*), void*);  //This is what I WANT TO USE
    void draw(Mat*, bool);
    void val(const char*);
    char value[30];
};

Now, there is the function that calls the callback:

bool Opencv_Button::mouse(int mx, int my, int button) 
{
    if(/*click conditions satisfied*/) 
        {
             /*CLICK!!!*/
                  if(callback!=0)
                     callback(callback_param);
                     /*Instead I WANT:*/
                     //callback(*this/*some THIS instance*/, callback_param);
                 return true;
        }
    return false;
}

So, I can do something like this in callback:

bool buttonCallback(Opencv_Button*but, void*param) {
     but->val("I was clicked!!!");
}
Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778

2 Answers2

1

You're pretty close. The quick fix is to make sure your callback takes a pointer and you pass this:

bool (*callback)(Opencv_Button*, void*);
void setCallback(bool(*)(Opencv_Button*, void*), void*);

And call with:

callback(this, callback_param);

However, you'd likely be better off using references. You can have your function take a reference to Opencv_Button:

bool (*callback)(Opencv_Button&, void*);
void setCallback(bool(*)(Opencv_Button&, void*), void*);

Then call it with:

callback(*this, callback_param);

And your buttonCallback will look like this:

bool buttonCallback(Opencv_Button& but, void* param) {
  but.val("I was clicked!!!");
}
Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • Shan't you use `.` to access class members in the last code example? Anyway, this is the answer. I decided to use `pointer` because I understand pointer mechanism better and references are confusing me. But thank you for posting both options! – Tomáš Zato Feb 23 '13 at 14:07
  • @TomášZato Apologies, you're right. However, you're much better off using references. Raw pointers should only be used if necessary in C++. – Joseph Mansfield Feb 23 '13 at 14:16
  • If you insist on using references instead of pointers, is there some reason for this? I already said I'm not sure I know everything about references, so I'll sure read some interesting article about their advantages. – Tomáš Zato Feb 23 '13 at 14:18
0

Define the callback as

bool (*callback)(Opencv_Button*, void*);

and everythinng goes fine.

Mohammad Dehghan
  • 17,853
  • 3
  • 55
  • 72