This question is based upon: Calling C++ class methods via a function pointer
What i would like to do is to register a generic object member function to a module lower in the architecture, that can invoke an event callback.
What i need is being able to register any object type (generic), so i do not have to have a registration function for each type of object.
Example from 1:
typedef void(Dog::*BarkFunction)(void);
Then to invoke the method, you use the ->* operator:
(pDog->*pBark)();
Example in my code:
// application layer
class ObjectInHighterLayer
{
ObjectInHighterLayer()
{
xyz::registerEventhandler(this, eventCallback); // ??? how to register here ???
}
void eventCallback(int x)
{
}
}
// middleware layer or hal layer
static clientcallback clientCb = NULL;
namespace xyz {
typedef void (GENERIC_OBJECT_TYPE::*clientcallback)(int /*x*/); // ??? how to define callback type here ???
void registerEventhandler(clientcallback cb);
{
clientCb = cb;
}
void task()
{
// ... if event happend
callClients();
}
void callClients()
{
if(clientCb != NULL)
{
clientCb(3);
}
}
}
There are two patterns I am aware of...
virtual
All the callback functions share a class hierarchy, so a single virtual function can be used to dispatch to the correct type.
class CallbackBase {
public:
virtual void anEvent(int myEvent) = 0;
};
This can be registered by a class directly.
class ObjectInHighterLayer
{
ObjectInHighterLayer()
{
xyz::registerEventhandler(this, eventCallback); // ??? how to register here ???
}
void anEvent(int myEvent)
{
// receive callback
}
}
Or indirectly (probably better to use std::function)
class Test {
public:
void callable(int ) {
}
};
typedef void (Test::*Callable)(int);
This can then be called by a proxy object, separating the hierarchy of the callbacks from that of the called.
class MyFunction {
public:
Callable m_f;
Test * m_Test;
MyFunction( Test * pTest, Callable fn) : m_Test(pTest), m_f( fn )
{
}
void anEvent( int x ) {
(m_Test->*m_f)(x);
}
};
Allowing different functions of test to be registered for different callbacks.
static callback
Change the callback mechanism to take an opaque type. This is easier to code, although sacrifices type-safety.
class Callbackable {
static void callback1( void * pThis, int param )
{
Callbackable *_this = static_cast<Callbackable*>( pThis );
_this->callFunction( param );
}
}
The callback1 because it is static shares a function type with similar functions in different classes (outside of any hierarchy). The idea that it is called with an incorrect pThis is the type safety weakness.
Related
I am a new in c++ maybe I miss something, but actually what I need to do is: I have a class that processing something in other thread, during this processing I need that it invoke a callback for progress.
How I see I can do it, I need to declarate pointer (maybe shared_ptr) for my callback function as a class member, than I have a setter in order to pass pointer to callback and then I can use it. A few issues here are how to pass it correctly? How to invoke pointer on function?
My implementation is:
class RobocopyCopy
{
//Public members
public:
typedef std::function<void(int)> TVoidIntCallback;
RobocopyCopy * set_monitoring_done_callback(TVoidIntCallback monitoring_done_callback)
{
m_pMonitoring_done_callback = &monitoring_done_callback;
return this;
}
//This method executes in background
void execute()
{
...
//and here I need to invoke my callback
(TVoidIntCallback *)m_pMonitoring_done_callback(777); //but this is not correct
private:
TVoidIntCallback * m_pMonitoring_done_callback;
...
}
and final implementation of this should be like this (I think) :
RobocopyCopy robocopy;
robocopy.set_monitoring_done_callback([this](int my_progress) {
printf("Progress is :: %d", my_progress);
});
So, as I mentioned above questions is :
how to pass this function callback as a lambda and save in Robocopy class as a pointer
How to invoke this function correctly, because this (TVoidIntCallback *)m_pMonitoring_done_callback(777); doesn't work.
I am using VC++ I hope this code will be successful for you.
class RobocopyCopy
{
typedef std::function<void(int)> TVoidIntCallback;
TVoidIntCallback evnt;
public:
RobocopyCopy* set_monitoring_done_callback(TVoidIntCallback
monitoring_done_callback)
{
//set callBack function from out side.
evnt = monitoring_done_callback;
return this;
}
void execute() {
//invoke your callBack
evnt(1000000);
}
};
int main()
{
RobocopyCopy obj;
obj.set_monitoring_done_callback([](int data) {
std::cout << data << "\n";
})->execute();
}
First of all sorry if the name of the question is not clear enough. I really have no idea on how to call this problem.
So I have a function pointer inside a class that works like a java callback that I invoke with some parameters like itself that is derived from a parent class like in this example:
class Parent;
using f_Call = void(*)(Parent*);
class Parent
{
public:
void setCallback(f_Call call)
{
mOnCall = call;
}
protected:
f_Call mOnCall = nullptr;
};
class Child1 : Parent
{
public:
void doSomething()
{
// some work..
if (mOnCall)
mOnCall(this);
}
};
void onCallExe(Parent* p)
{
Child1* child = (Child1*)p;
// do some more work...
}
int main()
{
Child1 child;
child.setCallback(onCallExe);
child.doSomething();
}
My question is if does c++ has a way of doing the cast from parent to children automatically in onCallExe so I don't have to do it for every function I call.
Thank you!
Don't use function pointers. Instead, you want std::function<void()> (yes, without arguments) and pass it a lambda with a captured object.
using f_Call = std::function<void()>;
class Parent {
public:
void setCallback(f_Call call) {
mOnCall = call;
}
protected:
f_Call mOnCall;
};
class Child1 : public Parent {
public:
void doSomething() {
// some work..
if (mOnCall)
mOnCall(); // no argument!
}
};
int main() {
Child1 child;
child.setCallback([&child](){ /* do whatever with the child */ });
child.doSomething();
}
If you want, you can hide creation of the lambda in a function template.
template <class Obj, class CB>
void setCallback (Obj& obj, CB cb) {
obj.setCallback([&obj](){cb(obj);});
}
and then pass the global setCallback template any old function with a Child argument.
void onCallExe(Child1& child) {
// do some more work...
}
Child1 child;
setCallback(child, onCallExe);
Curiously recurring template pattern might be an option. However, you'll create separate base classes for each derived one, so you couldn't use them polymorphically – unless you provided a separate, common base. If the recurring template function overwrites a virtual one in the base, you might end up at where you wanted to get:
struct Base
{
virtual ~Base() { }
virtual void f() = 0;
};
template <typename T>
struct Intermediate : Base
{
void f() override
{
if(callback)
callback(static_cast<T*>(this));
}
void setCallback(void(*c)(T*))
{
callback = c;
}
private:
void(*callback)(T*) = nullptr;
};
struct Derived : Intermediate<Derived>
{
};
void g(Derived*) { }
void demo()
{
Derived d;
d.setCallback(g);
d.f();
}
(If you don't need polymorphism, you can skip Base class – then f doesn't have to be virtual either.)
Solely if you wanted to set the callbacks via pointer or reference to Base, you are a bit in trouble, as you cannot have virtual template member functions. You could, though provide a free-standing helper function:
template <typename T>
void setCallback(Base& b, void(*callback)(T*))
{
dynamic_cast<Intermediate<T>&>(b).setCallback(callback);
}
The dynamic cast will throw a std::bad_cast if b is of inappropriate type – unfortunately a rather costly run-time thing, a safe way to let the compiler determine if pointed/referred object is of correct type (usually) is not possible.
I am creating a console menu in C++ and I want to give every item in my menu a callback function, so when an item is selected, a different function is called.
So far, I have this code:
#include <iostream>
#include <vector>
using namespace std;
class Core
{
public:
void action1() {}
void action2() {}
//...
};
typedef void (Core::*CoreFunc)();
class Menu
{
struct Option
{
Option(CoreFunc cb) : callback(cb) {}
//some data
CoreFunc callback;
//some more data
};
vector<Option> m_options;
public:
Menu(Core const& core)
{
addOption(core.action1);
}
void addOption(CoreFunc callback)
{
m_options.push_back(Option(callback));
}
void execOptionX(int index)
{
m_options[index].callback();
}
};
int main()
{
Core core;
Menu menu(core);
menu.execOptionX(0);
return 0;
}
Which is giving me this error:
no matching function for call to ‘Menu::addOption(<unresolved overloaded function type>)’
at addOption(core.action1);
and also
must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘((Menu*)this)->Menu::m_options.std::vector<_Tp, _Alloc>::operator[]<Menu::Option, std::allocator<Menu::Option> >(((std::vector<Menu::Option>::size_type)index)).Menu::Option::callback (...)’, e.g. ‘(... ->* ((Menu*)this)->Menu::m_options.std::vector<_Tp, _Alloc>::operator[]<Menu::Option, std::allocator<Menu::Option> >(((std::vector<Menu::Option>::size_type)index)).Menu::Option::callback) (...)’
when I try to call the function.
I have seen many implementation of member function pointer, but they are all used within the same class.
Why am I getting these errors?
What is the correct syntax to get this code to compile/work?
Thank you
You declared CoreFunc as a non-static pointer-to-member-method. So you need to specify a pointer to the desired method, eg:
addOption(&Core::action1);
More importantly, you also need to provide a Core object instance as the this parameter for the callback. You specify the object via the .* operator (if using an object reference) or the ->* operator (if using an object pointer), eg:
void execOptionX(int index)
{
CoreFunc callback = m_options[index].callback;
(SomeCoreObj.*callback)();
}
void execOptionX(int index)
{
CoreFunc callback = m_options[index].callback;
(SomeCoreObjPtr->*callback)();
}
So, you need to change your Menu class to keep track of the Core object that will be passed to the callback (assuming you don't want to pass the Core object as a parameter to execOptionX(), eg:
class Menu
{
struct Option
{
Option(CoreFunc cb) : callback(cb) {}
//some data
CoreFunc callback;
//some more data
};
Core &m_core;
vector<Option> m_options;
public:
Menu(Core &core)
: m_core(core)
{
addOption(&Core::action1);
}
void addOption(CoreFunc callback)
{
m_options.push_back(Option(callback));
}
void execOptionX(int index)
{
CoreFunc callback = m_options[index].callback;
(m_core.*callback)();
}
};
And of course, the Core object has to remain alive for the lifetime of the Menu (which it does in your main() example).
Here is my MESSAGE structure:
struct tEventMessage
{
// Type of the event
int Type;
// (void*) Allows those to be casted into per-Type objects
void *pArgument1;
void *pArgument2;
};
Can i add some kind of 'template' member to this structure, so that later on when building message i can pass those pointers + and any other data i wish ? ( see example below )
struct tEventMessage
{
// Type of the event
int Type;
// (void*) Allows those to be casted into per-Type objects
void *pArgument1;
void *pArgument2;
// Template
T tSomeTemplateMember;
};
void HandleClick(....)
{
CVector3 vNewPosition = ....
tEventMessage _msg;
_msg.Type = xxxx;
_msg.pArgument1 = pA->GetObjectPointer();
//
// Wrong!
// Because this CVector3 will not be alive in next tick
// - my pointer will point to nothing.
//
_msg.pArgument2 = static_cast<CVector3*>(&vNewPosition)
//
// Something like that would be great
// And would allow me to use CVector2,CVector3,CVector4 with one template member
//
_msg.tSomeTemplateMember = vNewPosition;
}
I think you're over complicating the problem. Instead of one problem, how to pass arbitrary data in a message, you now have two, how to cope with templates as well.
The usual method to implement this sort of thing is to use inheritance:-
class Message
{
public:
int Type () { return type; }
protected:
int type;
};
class ClickMessage : public Message
{
public:
ClickMessage () { type = ClickMessageID; }
private:
// the message data
};
void HandleMessage (Message *message)
{
switch (message->Type ())
{
case ClickMessageID:
HandleClick (reinterpret_cast <ClickMessage *> (message));
break;
default:
// unhandled message error
break;
}
}
void HandleClick (ClickMessage *message)
{
// do stuff
}
The problem is you end up repeating a lot of code, i.e the cast in the switch statement. There's also a maintenance issue too - added new messages requires a bit of careful updating. You could hack the code a bit and use function pointers and a map to convert message types to functions and replace the switch statement.
There might be a clever template solution, but I can't think what it might be.
Using RTTI might help (at a cost).
This is one problem that reflection is really good at solving!
Perhaps I am missing something however I am wondering why you do not start with an abstract class from which you then derive your various kinds of event messages. By taking advantage of abstract classes and deriving classes from them, you let the compiler figure out the logic that you are using a switch statement for. See this C++ Polymorphism and Abstract Base Class tutorial.
Also see this from MSDN on Abstract classes.
For instance you might have an abstract class that looks like the following. However you may not want as much of this and in fact may just want the single processEvent() method only. Any derived classes will need to provide their own versions of each of the functions specified in the abstract class.
class EventMessage abstract {
public:
virtual void *getArgument1 (void) = 0;
virtual void *getArgument2 (void) = 0;
virtual int processEvent (void) = 0;
protected:
void *pArgument1;
void *pArgument2;
};
What this abstract class defines is a class that basically contains the data that is used by all of the various event messages along with a method that is called to process the the actual message. The class itself is not instantiated however it is used as the parent or super class for other derived class that are actually instantiated as objects.
What you would then do is to derive new classes that would implement the EventMessage interface. For instance here are two different classes that would do that:
class JoJoEvent : public EventMessage {
public:
JoJoEvent(void *arg1, void *arg2);
void *getArgument1 (void);
void *getArgument2 (void);
int processEvent (void);
};
JoJoEvent::JoJoEvent(void *arg1, void *arg2)
{
pArgument1 = arg1;
pArgument2 = arg2;
}
void * JoJoEvent::getArgument1 (void) {
return pArgument1;
}
void * JoJoEvent::getArgument2 (void) {
return pArgument2;
}
int JoJoEvent::processEvent (void) {
// do stuff with the arguments
return 1;
}
class KoKoEvent : public EventMessage {
public:
KoKoEvent(void *arg1, void *arg2);
void *getArgument1 (void);
void *getArgument2 (void);
int processEvent (void);
};
KoKoEvent::KoKoEvent(void *arg1, void *arg2)
{
pArgument1 = arg1;
pArgument2 = arg2;
}
void * KoKoEvent::getArgument1 (void) {
return pArgument1;
}
void * KoKoEvent::getArgument2 (void) {
return pArgument2;
}
int KoKoEvent::processEvent (void) {
// do stuff with the arguments
return 1;
}
Then when using these you would do something like the following code:
EventMessage *myMessage = new JoJoEvent(0, 0);
EventMessage *myMessage2 = new KoKoEvent(0, 0);
myMessage2->processEvent();
myMessage->processEvent();
If you need to add additional data into the derived classes you can do so just provide a mechanism to put the data into the derived class.
What should I do if I want to pass a non-static member function of any class as a click function of the button ? Is it possible ? If so what do I need to do ? For example in which ever class (EntityToolGUI over here) the button is initiatlized, I want to set its click action to a non-static member function (a non-static member function of class EntityToolGUI ) of that class.
GUIButton.h
typedef void (*ptr2clickFunc)(void);
class GUIButton : public GUIObject {
private : void (*clickFunc)(void);
public : void setClickFunction(ptr2clickFunc clickFunc);
};
GUIButton.cpp
void GUIButton::setClickFunction(ptr2clickFunc clickFunc)
{
this->clickFunc = clickFunc;
}
EntityToolGUI.h
class EntityToolGUI {
public : EntityToolGUI();
protected : void addAnimation();
}
EntityToolGUI.cpp
void EntityToolGUI::addAnimation()
{
cout<<"add animation"<<endl;
}
EntityToolGUI::EntityToolGUI()
{
....
btnAddAnimation->setClickFunction(&EntityToolGUI::addAnimation);
}
I am getting an error no matching function call to GUIButton::setClickFunction(void (EntityToolGUI::*)())
candidate is void GUIButton::setClickFunction(void (*)())
How do I solve this ?
Most (decent) C code that passes function pointers around use an extra void* argument for passing user context to the function. This is not so common in C++ (as better techniques than function pointers exist), but if you're stuck using function pointers for some reason then it may be appropriate.
typedef void (*ptr2clickFunc)(void*);
class GUIButton : public GUIObject {
private : ptr2clickFunc clickFunc;
private : void * userdata;
public : void setClickFunction(ptr2clickFunc clickFunc, void* userdata);
};
class Foo
{
static void do_foo( void * userdata )
{
Foo* thisptr = static_cast<Foo*>(userdata);
thisptr->foo();
}
void foo() { ... }
};
int main()
{
Foo foo;
GUIButton button;
button.setClickFunction( &Foo::do_foo, &foo );
button.click();
}
EDIT As noted by Bartek, if you're doing this a lot you can extract the static function into a template - it looks a bit like this (untested and probably with minor errrors).
// GUIButton is as before
// Note no static function here
class Foo { void foo(); }
template<typename T, void(T::*FN)() >
void Call( void * data)
{
static_cast<T*>(data)->*FN();
}
int main()
{
Foo f;
GUIButton button;
button.setClickFunction( &Call<Foo,&Foo::foo>, &f );
button.click();
}
If you want to pass obj fun ptr you can use boost::bind and boost::function
http://www.boost.org/doc/libs/1_50_0/libs/bind/bind.html
You cannot pass a pointer to non-static member function as a pointer to a "regular" non-member function. You should either make addAnimation static, or make ptr2clickFunc typedef a pointer to member function.
Note that invoking a pointer to member function is different from invoking a function pointer, because you must supply an instance on which the member pointer is to be invoked.
addAnimation needs to be static function. When the call back function is set the way you are doing it now, the object of class EntityTollGUI is not registered along with the function.
Try this one (C++11):
#include <stdio.h>
#include <stdlib.h>
#include <functional>
class Raiser
{
public:
std::function<void(int)> ev1, ev2;
void RaiseEv1()
{
if (!ev1._Empty())
ev1(44);
}
void RaiseEv2()
{
if (!ev2._Empty())
ev2(66);
}
};
class Handler
{
private:
int id;
std::function<void(int)> h;
public:
Handler(int newId)
{
id = newId;
h = [this](int i)
{
printf("Handler with id = %d captured event!\n", this->GetId());
};
}
void Hook1(Raiser & raiser)
{
raiser.ev1 = h;
}
void Hook2(Raiser & raiser)
{
raiser.ev2 = h;
}
int GetId()
{
return id;
}
};
int main(int argc, char * argv[])
{
Raiser raiser;
Handler handler1(1), handler2(2);
handler1.Hook1(raiser);
handler2.Hook2(raiser);
raiser.RaiseEv1();
raiser.RaiseEv2();
getchar();
}
AFAIK, this is the most you can get with events in C++ without using language extensions.