So I have this function:
void EventDispatcher::Subscribe(string eventName, void (*callback)(void *))
{
....
}
I am trying to pass class member function as a callback parameter there.
typedef void (*method)(void*);
void EventTester::RunTests()
{
_dispatcher = new EventDispatcher();
Event eventOne("one");
_dispatcher->Register("one", eventOne);
method p = &onOne;
_dispatcher->Subscribe("one", p);
}
void EventTester::onOne(void *args)
{
std::cout<<"Event one\n";
}
obviously this doesn't compile because onOne is not static and a member function. Is there any way of making it work this way?
You could use boost in C++03 or std::bind and std::function in C++11:
typedef boost::function<void(void*)> func_type;
void EventDispatcher::Subscribe(const string& eventName, const func_type& func_)
{
if ( ! func_.empty() ) {
// you could call the function
func_(NULL);
}
}
//Register looks like in a member function of EventTester:
...
_dispatcher->Subscribe("one",boost::bind(&EventTester::onOne,this,_1));
...
I'm going off the assumption that you have the ability to modify the signature of Subscribe. If not, my answer may not apply.
As you already noted, your pointer-to-member (aka method) is not the same as a plain function pointer. To use a pointer-to-member, you have to supply the class instance to call the function on as part of the method execution.
You could modify Subscribe to explicitly take in a pointer-to-member, which would expect an additional argument (the class instance). You would need Subscribe to store both the function pointer, and a pointer to your object instance. This would then require that all callbacks be implemented as pointers-to-members.
The preferred way to solve this problem is to use bind (either std::bind or boost::bind).
You would need to change your Subscribe function to take in a std/boost::function object instead of an explicit function pointer. This would permit callers of the Subscribe method to pass in any callable object (See the examples in the documentation of std::function)
You can then use bind to connect your class instance to your method pointer. This will return a functor object which will do the work of holding both your pointer-to-member and a pointer to your class instance.
For an example of how to use bind, see this link
Related
std::vector<char>function(std::string word) {
}
namespace::json getList(){
function();
}
I was just wondering if im suppose to call the function on top by including std::function(argument)
No, you don't need nor should you use the std::function class to call function. The std::function class is more like a function pointer wrapper. It lets you work with functions as data more easily.
For example, std::function<T> func represents some parameterless function that returns an object of type T.
Refer to the documentation for std::function for more information.
I have this typedef function on Class A.h:
typedef void(*PERCENTAGE_CALLBACK)(float);
And I am using on one of the class' function:
int API_GenerateLayerData(int layerIndex, unsigned char *data, int dataSize, PERCENTAGE_CALLBACK callback);
In Another Class (ClassB.cpp), I have this function that returns nothing(void) but accepts a float value just like PERCENTAGE_CALLBACK:
void ClassB::Update(float progress)
{
emit ChangeProgress((int)progress);
}
But when I initialize the PERCENTAGE_CALLBACK object to be used and passed on the function in the ClassA it throws an error:
public void someFunction()
{
ClassA *a = new ClassA();
PERCENTAGE_CALLBACK callback = &ClassB::Update; //Error: cannot convert void ti PERCENTAGE_CALLBACK
a->API_GenerateLayerData(someNum, someData, count, callback);
}
How do I initialize the Class A's callback that points to the Class B's Update Function?
You simply can't do that because calling a member function also needs a object on which the member should be called.
If your api only provide a function pointer, independent of which signature it is, you can't work around this problem even not by std::bind nor by using lambda functions. Both of them are also "callable" objects and as this, they also need a object pointer or reference for the callback.
If you are able to change your API you are using, you should change the callback registration to std::function. std::function is able to handle plain function pointers and also lambdas or any other combination of object/method combination.
I don't understand why the following code compile and works:
template<typename Predicate>
void foo(Predicate p) {
}
bool g(int n) {
}
void user(int n) {
foo(g);
}
foo is supposed to get a function object that will run on a data structure but I made the method simpler, because what I don't understand is how can this works? A method isn't an object. The normal way to do it is to create a new class, override operator() and then send an instance of that class.
Well, in this case the Predicate parameter is substituted by a function pointer of type bool (*func) (int). Nothing wrong with that...
The Predicate template argument can be almost any type. So you can use it for function pointers and classes as well as the basic types.
If you use the function argument p as a function, then it can be anything that is callable, like a function pointer, an object whose class have an operator() member function, a pointer to a static member function, a std::bind object, a std::function object or a lambda expression.
It can't be a pointer to a member function though, because to call a pointer to a member function you need an instance to call it on. For this use std::bind.
I have two classes that don't know anything about themselfs class A, class B.
Class A is called the ENGINE,
Class B is called the GUI.
I want GUI class to have a pointer to a function in class ENGINE, so that when an event occurs on GUIControl, it calls ENGINE member function with two parameters (int,int).
Here's how i would like to have it:
class CGUIManager
{
public:
void SetControlCallback(void(*pFunctionPointer)(int,int) );
private:
void (*m_pControlCallbackFunction)(int,int) ;
};
void CGUIManager::SetControlCallback(void(*pFunctionPointer)(int,int) )
{
if(pFunctionPointer)
m_pControlCallbackFunction = pFunctionPointer;
}
class CEngine
{
private:
void GUIControlsCallback(int iControlID, int iControlMessage);
CGUIManager *pGUI;
};
Now while initializing ENGINE, i want to call:
//Set Controls Callback to CEngine Method
pGUI->SetControlsCallback( GUIControlsCallback );
To register a callback within CGUIManager class, that points to a method in CEngine class.
How can i do that?
Thanks in advance.
I would suggest using an interface (or something like that) if you would like it to be oo instead of function pointers ( which must point to a static member btw )
class IGuiCallback
{
public:
virtual void GUIControlsCallback(int iControlID, int iControlMessage)=0;
};
class CGUIManager
{
public:
void SetControlCallback(IGuiCallback*);
private:
IGuiCallback* m_pCallback;
};
class CEngine:public IGuiCallback
{
public:
void GUIControlsCallback(int iControlID, int iControlMessage);
private:
CGUIManager *pGUI;
};
then in engine:
pGUI->SetCallback(this);
There may be some syntax errors in my code but you should get the picture
Pointers-to-member-functions are not function pointers in C++.
To call your callback later (using provided SetControlsCallback signature), the caller need to have a valid instance of CEngine. You can achieve that by binding the pointer to CEngine to GUIControlsCallback:
CEngine* pEngine; // initialized somewhere
pGUI->SetControlsCallback(std::bind1st(pEngine, GUIControlsCallback));
If you use Boost or C++11, you'd better use their versions of bindings (boost::bind or std::bind respectively).
The easiest approach is to use std::function<void(int, int) as the type of the registered callback: this object can be used to call any function [object] which is callable with two ints. In particular, it could call the member function CEngine::GUIControlsCallback(int, int) which actually has three parameters:
the two obvious parameter to the member function of type int
the implicit pointer to the object (which becomes this)
The way this is done is to construct a function object which provides as first parameter a pointer to the CEngine object and takes two integers:
struct CEngine_bind {
CEngine_bind(CEngine* engine): engine_(engine) {}
void operator()(int i0, int i1) { this->engine_->GUIControlsCallback(i0, i1); }
CEngine* engine_;
};
Alternatively, you can use std:bind() which is a create a suitably bound function:
CEngine engine; // ... wherever this object is coming from)
std::function<void(int, int)> callback(std::bind(&CEngine::GUIControlsCallback, &engine,
std::placeholders::_1, std::placeholders::_2));
... and then set the callback object as the callback. This object simply be called passing two integer parameters which will cause the member function on the referenced object to be called:
callback(10, 20);
would call
engine.GUIControlsCallback(10, 20);
The std::function<void(int, int)> is copyable, i.e. you can easily store it in your CGUIManager class.
If you are able to change the interface of the CGUIManager class, I ssugest you generalise it to use boost::function<void(int, int)> (or std::function if writing in C++11) instead of a function pointer.
If you can't, unfortunately you are a victim of bad design. C-style callbacks that use function pointers usually allow for some kind of void* user data parameter to carry any additional information bound to the callback - in this case the your CEngine pointer could be cast to void* and a free function wrapper could be written to cast the void* back to CEngine. However, if you are able to change the callback interface, using boost/STL function is a superior technique.
I would need a member function to be passed into a third party external method:
box_self_intersection_d(mycallback);
The box_self_intersection_d is a third party external static method, and I cannot modify it. mycallback is a method I want to pass it into the box_self_intersection_d, it is a class function and is accessing some members in this class ( have full control for this class and the mycallback)
Is there anyway I can use class member functions as callbacks without declaring them as static functions?
Edit: the signature of mycallback is (const box &boxA, const box &boxB), where box is a special class from the third party provider.
And the signature for box_self_intersection_d is
void box_self_intersection_d(RandomAccessIterator begin,RandomAccessIterator end,Callback callback)
If the function box_self_intersection_d takes a functional as parameters, and mycallback is a method of a class MyClass, you can use boost::bind:
box_self_intersection_d( boost::bind( &MyClass::mycallback, myClassInstance ) );
where myClassInstance is the instance of the class MyClass.
If the callback accepts a void* for user-defined data, you can use a static wrapper function that casts the void* argument to the class type and calls your member function.
Example:
static void Foo::callback_method(void* data) {
static_cast<Foo*>(data)->mycallback();
}
void Foo::register_my_callback() {
box_self_intersection_d(&Foo::callback_method, this);
}
Most sane callback libraries allow you to pass this void* argument to the functions as a way to have user-defined data in it. If not, you'll need to resort to the dirty method:
static Foo* Foo::callback_object;
static void Foo::callback_method() {
callback_object->mycallback();
}
void Foo::register_my_callback() {
callback_object = this;
box_self_intersection_d(&Foo::callback_method);
}
In general, if you need to pass a function, there is just no other way: Either you have a data side-channel like the void*, which your library provider seems to have omitted (and is clearly a bug in the library), or you need to transport the this pointer via a global variable.
There are a couple of possible workarounds. You can have a look here: http://www.newty.de/fpt/callback.html#member
In short, you can either:
declare a static "wrapper method" and pass the instance of the class to it,
or else store a pointer to the object as a global variable.
Hope that helps,
You haven't provided the signature box_self_intersection_d()
in general, if the signature is
void box_self_intersection_d( void *cb );
or even
void box_self_intersection_d( void (*cb)(const box&, const box&) );
then you cannot pass it a pointer to a member function.
The reason is that sizeof(a_member_function) is different than
sizeof(a_function_pointer). If this is the case, I think you are forced to use thiton's solution, and create a static function.
Since it's CGAL, the callback is actually a template parameter.
Its only constraints are "Callback must be of the BinaryFunction concept".
That is, it can be anything that is "callable" with the proper parameters.
This includes any object with a void operator() (const box&, const box&) member function.
Implementing that function in your class and passing *this for the callback would probably be the simplest solution.
There is a horrible solution that I can conceive of that means copying/pushing 'this' and function code to the calling stack, (or some other caller-allocated segment that can be made writeable and executable), and passing the address of the function to the library. The called-back function could then find its own code address, extract 'this' using an offset/pointer arith. and call a member function. Should work for multiple threads.
I hereby claim this years 'Gruesome Hack' award for a solution that makes developers feel physically ill but might still actually work if a project manager is pointing a shotgun at your head.
Rgds,
Martin