Class member function as callback using boost::bind and boost::function - c++

I'm working through setting up a member function as a callback for a C-library that I'm using. The C-library sets up callbacks like this:
typedef int (*functionPointer_t)(myType1_t*, myType2_t*, myType3_t*);
setCallback(param1, param2, functionPointer, param4)
I would like to use boost::bind (if possible) to pass in the function pointer. I would prefer that the function being pointed to was a member of the instantiated class, not a static member. E.g.
Class A {
public:
A();
protected:
int myCallback(myType1_t*, myType2_t*, myType3_t*); //aka functionPointer_t
}
Can this be done using boost::bind and boost::function? Per How can I pass a class member function as a callback? (the 3rd answer) it appears that I could declare the following (somewhere, or as a typedef):
boost::function<int (A*, myType1_t*, myType2_t*, myType3*> myCallbackFunction
And then somewhere in A (the ctor) call boost::bind on that type, and pass it into the C-library call.
Is this possible, or am I off base? Thanks much.

No. Functor types like boost::function don't convert to function pointers for use with C callback mechanisms.
However, most C callback mechanisms have some kind of token mechanism, so your callback function (which is static) has some kind of context information. You can use this to write a wrapper class which maps these tokens to functor objects, and passes execution along to the right one:
class CallbackManager {
public:
typedef boost::function<int (type1*, type2*, type3*)> callback;
static void setCallback(CallbackManager::callback cb)
{
void *token = ::setCallback(staticCallback);
callbacks[token] = callback_I;
}
static void staticCallback(void* token, type1* a, type2* b, type3* c)
{ return mcallbacks[token](a, b, c); }
private:
static std::map<void*, callback > callbacks;
};

do not use map, it gives runtime overhead and clutter up code with static map.
use reinterpret_cast instead.
for instance
// clib.h
typedef void (*CALLBACK_FUNC)(int code,void *param);
void set_callback( CALLBACK_FUNC, void * param );
// a.h
class A {
public:
A()
{
::set_callback( &A::static_callback, this);
}
private:
static void static_callback(int code, void * param)
{
A* self = reinterpret_cast<A*>(param);
self->callback( code );
}
inline void callback( int code )
{
// write you code here.
}
};

The problem with member functions is that they automatically receive a pointer to object instance as the first parameter - "this" pointer. That's why you can't use member functions a C callback functions. You must have the object AND the function pointer together in order to use a member function.

Related

How to convert void (myClass::*)() to void (*)()

I'm currently working on a C++ project on the Unreal Engine and I can't wrap my head around this problem.
class A
{
public:
void (* array[10])();
//Add Function to an array
void AddFunctionToArray(void(*function)());
};
class B
{
public:
A a;
//Sending a B function to A
void SendMyFunction();
void Foo();
};
void B::SendMyFunction()
{
a.AddFunctionToArray(&B::Foo);
}
I get the error: can't convert void (B::*)() to void (*)()
How can I send a function pointer from one of my class to another?
void (B::*)() is a pointer to a non-static member function, while void (*)() is a pointer to a non-member function. There is no conversion between the two.
Making B::Foo static would fix this problem. However, you will have no access to instance members of B.
Note that using function pointers, member or non-member, is an old style of passing function objects. A more modern way is using std::function objects, which can be constructed from a combination of an object and one of its member functions.
If you're looking to have class A execute a method from an arbitrary class X you can try this:
template <typename UserClass>
void A::FireMethod(UserClass* InUserObject, typename TMemFunPtrType<false, UserClass, void(int)>::Type InFunc)
{
(InUserObject->*InFunc)(15);
}
In this case we're calling a function with a single int as argument. A class B could do this:
A* a = myAObject;
a->FireMethod(this, &B::MyMethod);
with
void B::MyMethod(int) {}
Hope this helps you! If you want more information, in unreal engine you can look at the AddDynamic macro in Delegate.h

Method of one class as callback from another

I will describe my problem the simplest as I can.
What is my issue:
I have frist class as a singleton:
class CTimer1
{
public:
static CTimer1 * getInstance(); //This gives me pointer to instance
void setChannelA(uint8_t compareValue);
private:
//Cnstructors
CTimer1(); //Prevent consttuction but allow in getInstance
CTimer1(const CTimer1&); //Prevent construction by copying
CTimer1& operator=(const CTimer1&); //Prevent assigment
~CTimer1(); //Prevent unwanted destruction
static CTimer1 * timerInstance;
static bool isCreated;
};
And here is second class where I would like to have possibility to call setChannelA method from CTimer1 class as a setPwm method from CServo class:
class CServo {
public:
CServo();
~CServo();
public:
//public methods
void registerPwmTimer(void (*callback)(uint8_t u8_buffer));
void (*setPwm)(uint8_t u8_buffer); //As this method I would like to call setChannelA from CTimer1 class
};
Here is registerPwmTimer method:
void CServo::registerPwmTimer(void (*callback)(uint8_t u8_buffer))
{
setPwm = callback;
}
Then I have tried to assign pointer to this method as a following:
int main()
{
CTimer1 * timer1 = CTimer1::getInstance();
CServo servo1();
servo1.registerPwmTimer(timer1->setChannelA);
servo1.setPwm(10); //This is example how I want to call setChannelA method
while(1)
{
}
}
I have error:
error: no matching function for call to 'CServo::registerPwmTimer(<unresolved overloaded function type>)'
What is important:
I can't use std::function because this is some part of code in C++ for embedded device, so I need to save memory consumption. Is there any way that I will be able to achieve this effect? If ony one possibility to do this is ot use some std library please for answers too. Thanks for your help.
Your problem is that a function pointer necessarily has to point to a static function. When you invoke an instance function (a method) there is a hidden first argument, which is the object on which the function was invoked. (This hidden argument is available as this within the function's definition.)
Your CServo::registerPwmTimer() function signature is simply incompatible with invocation of a member function; function pointers alone do not provide a way to bind an argument to the pointer, so even if you could convey the member function pointer using a (free) function pointer type, the hidden this argument could not be determined when the function pointer was invoked.
To put it another way, it would fail for the same reason that trying CTimer1::setChannelA(0) would fail -- you want to invoke that method, but you haven't communicated which object on which to invoke it.
Change the signature of CServo::registerPwmTimer to accept an std::function object instead of a raw function pointer. std::function objects can be constructed from function pointers, but they can also be constructed from lambdas, and some standard library functions return function objects:
void registerPwmTimer(std::function<void(uint8_t)>);
Now, you can use std::bind to create a new function that binds the object instance to the member function pointer:
servo1.registerPwmTimer(std::bind(&CTimer1::setChannelA, timer1));
Note that std::bind does not extend the lifetime of the object pointed to by timer1. If the returned function is invoked after that object is destructed, the result is undefined behavior.
Another alternative would be to accept both an instance and a pointer to a member function. The problem with this approach is it requires using templates:
template <typename T>
void registerPwmTimer(void (T::*)(uint8_t), T&);
This isn't bad in itself, but what you'll wind up doing is creating a polymorphic wrapper class so that you can insert this into your callback list alongside other callbacks that don't share the same T. At that point, you're just recreating std::function, since std::function already serves the purpose of being a polymorphic wrapper around callable things.
To illustrate the mess of implementing a polymorphic callable wrapper yourself, here is a very light example. I will show the declarations of a set of these types, and link to an example implementation.
This is the base type, with a pure virtual operator() that serves as the invocation operation.
class poly_callable
{
public:
virtual void operator()(int) const = 0;
};
Now we have a type for function pointers (also works with pointer-to-functor):
template <typename T>
class fn_poly_callable : public poly_callable
{
public:
typedef T fn_type;
fn_poly_callable(T);
virtual void operator()(int) const;
private:
T fn;
};
And one for member functions -- oh, but const member functions and non-const member functions are not interchangeable, so we need an extra template parameter for that:
template <typename T, typename M = void (T::*)(int)>
class member_poly_callable : public poly_callable
{
public:
typedef T object_type;
typedef M member_fn_type;
member_poly_callable(member_fn_type, object_type&);
virtual void operator()(int) const;
private:
member_fn_type mfn;
object_type& target;
};
Plus we'll want some helper functions to allow the compiler to infer the template types. One for function pointers:
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(T fn)
{
return std::unique_ptr<poly_callable>(new fn_poly_callable<T>(fn));
}
Two for member functions (const and non-const):
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int), T& target)
{
return std::unique_ptr<poly_callable>(new member_poly_callable<T>(mfn, target));
}
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int) const, T& target)
{
return std::unique_ptr<poly_callable>(new member_poly_callable<T, void (T::*)(int) const>(mfn, target));
}
If you want to see it all in action, I made a "simple" and working example.
So... just use std::function. There's no reason to reinvent this stuff.

Pass member function to C interface requiring callback

I have an old .dll with plain C interface which takes callbacks to invoke when some work is done. The callback it takes is of type void (f*)(char* arg).
I'm looking for a trick to pass a C++ function object there so that the callback is invoked with "this" pointer stored somewhere, something like bind, but simple bind doesn't work
To illustrate this: C interface:
typedef void (f*)(char* param) Callback;
void registerCallback(Callback c);
Usage in C++:
class A
{
void func1()
{
registerCallback(std::bind(&A::func2, _1, this)); // obviously doens't work
}
void func2(char* param)
{ ... }
};
The only way that to make this work with an instance of a class and a member function of the class, that I am aware of, is:
Store a pointer to an object in a global variable.
Register a non-member function.
Call the member function from the non-member function using the global variable.
class A
{
void func1();
void func2(char* param)
{ ... }
};
// Global pointer
A* aPtr = NULL;
// Non-member function.
// extern "C" is probably needed if the older DLL is expecting
// an unmangled C function pointer.
extern "C" void globalFunc2(char* param)
{
if ( aPtr == NULL )
{
// Deal with error
}
else
{
aPtr->func2(param);
}
}
void A::func1()
{
aPtr = this;
registerCallback(globalFunc2);
}
The way I see it, the core of the problem is letting the caller of the callback function (the entity registerCallback is registering with) know which A object's func2 to call.
As far as I can understand from your problem, you basically have a bunch of A objects and you only want a number of these A objects to execute their respective func2s when the callback event occurs. However, the caller of the callback function does not know who to call when the callback event occurs. Since you mentioned that it's an old .dll, I assume we cannot just go in and change how registerCallback works, but we need to store the A objects that are registered for callback.
Therefore,
class Informer {
public:
static void InformAllMembers(char* param) {
for(auto& a : m_Members) { //Inform all As registered with me
a->func2(param);
}
}
static void Register(A* a) {
m_Members.push_back(a);
}
private:
static std::vector<A*> m_Members;
};
std::vector<A*> Informer::m_Members;
...
registerCallback(Informer::InformAllMembers);
A a;
Informer::Register(&a);
NOTE: You will have to handle cases where some of the registered A objects are destroyed and unregister them from the Informer.
This is simply an alternative to #RSahu's solution using static members in A class. IMHO, is is functionnally the same as global variables, but at least you get a namespace containment in you class:
class A
{
static A* current_obj;
public:
void func1()
{
current_obj = this;
registerCallback(func3);
}
private:
void func2(char* param)
{ ... }
static void func3(char *param) {
if (NULL == current_obj) {
// error ...
}
current_obj->func2(param);
}
...
};
And as demonstrated above, the registered functions can be private to the class, because the only function that need to be called externally is here func1.
But it suffers the same problem: you can register only one object at the same time.
Maybe I'm not understanding the problem but why not just build a simple wrapper to hold the "this" pointer. So, the application will use this callback (or lambda)
void RegisterCallback_withthis(char* arg, void* thisptr)
Only a single callback function can be registered with the DLL at one time. So, a single global thisptr is good.
static void* thisptr;
void RegisterCallback(char* arg)
{
RegisterCallback_withthis(argc, thisptr);
}
The application will have to setup the thisptr while registering the callback.
thisptr = this;

Most general way to receive a functor as a parameter?

I am writing a wrapper for a multithreaded scheme. It should operate similar to a timer.
I have a particular class (clock) that implements a function called tick which should be passed to constructor. How do I describe a C++ style function (myClass::myfunction, as opposed to the C convention) as the parameter to a method or constructor?
Would anybody be kind enough to show me the declaration for this kind of constructor?
clock myInstance(otherClass::aMethod)
myInstance.tick(); // Should call otherClass::aMethod
myInstance.tick();
Does C++11 and Bind help?
You can either call a static member function of a class or a non-static member function of an object. A non-static member function needs to have the context of an object (this pointer).
Here's a simplified example of how you can use functors and bind to call a member function.
#include <functional>
class clock
{
public:
clock(const std::function<void()>& tocall) : m_tocall(tocall) {}
void tick() {m_tocall();}
private:
std::function<void()> m_tocall;
};
class otherclass
{
public:
void aMethod() {}
};
int main(int argc, char *argv[])
{
otherclass A;
clock c( std::bind(&otherclass::aMethod, &A) );
c.tick(); // Will end up calling aMethod() of object A
}
You need not to use std::function for this. You need to have TWO pointers: One is the class-object, and one to the method of that class. In simple terms, you need to make it able to do:
CallNonVirtual(pClassPtr, pFuncAddr);
And therefore, you need both parameters, so that you can actually call it like:
(pClassPtr->*pFuncAddr)(); // Assuming no parameter
For this, you can do:
class Clock
{
COtherClass* pClassPtr;
/// Typedef simplifies
typedef void (COtherClass::*TargetFuncType)();
TargetFuncType pFuncAddr;
public:
Clock(COtherClass* pOther, TargetFuncType pFunc) :
pClassPtr(pOther), pFuncAddr(pFunc)
{
}
void tick()
{
(pClassPtr->*pFuncAddr)();
}
};
And make a call:
int main()
{
COtherClass Obj;
Clock theClock(&Obj, &COtherClass::TheNonStatic);
theClock.tick();
}

How to pass a method as callback to another class?

I have a question regarding callbacks using tr1::function. I've defined the following:
class SomeClass {
public:
typedef std::tr1::function<void(unsigned char*, int)> Callback;
void registerCallback(Callback);
private:
Callback callback;
}
I've defined another class:
class SomeOtherClass {
void myCallback(unsigned char*, int);
}
Now I want to register my function 'myCallback' as callback at class 'SomeClass'using the method 'registerCallback'. However, it is not working. I've had a look on the boost documentation on the function and it seems legit to use (member) methods of a class for callbacks. Am I wrong?
Thanks in advance!
Member functions have an implicit first parameter, a this pointer so as to know which object to call the function on. Normally, it's hidden from you, but to bind a member function to std::function, you need to explicitly provide the class type in template parameter.
#include <functional>
#include <iostream>
struct Callback_t {
void myCallback(int)
{
std::cout << "You called me?";
}
};
class SomeClass {
public:
SomeClass() : callback() { }
typedef std::function<void(Callback_t*, int)> Callback;
// ^^^^^^^^^^^
void registerCallback(const Callback& c)
{
callback = c;
}
void callOn(Callback_t* p)
{
callback(p, 42);
}
private:
Callback callback;
};
int main()
{
SomeClass sc;
sc.registerCallback(&Callback_t::myCallback);
Callback_t cb; // we need an instance of Callback_t to call a member on
sc.callOn(&cb);
}
Output: You called me?;
Why all this complicated mumbo-jumbo?
Why not create a class as thus (for example)
Class MouseOverEventCallBack
{
public:
virtual void RunMouseOverCallback() = 0;
};
Then just create classes that inherit this class (and redefine the method RunMouseOverCallback)
Then Register function just needs to be
void registerCallback(MouseOverEventCallBack *callbackObject); // possible could use a reference
The register method will just call the method and the object will have all that it needs.
Seems a bit simpler. Let the compiler do the work with pointers to functions etc.
the function void (*)(unsigned char*, int) is a free function, which is a different type from void (SomeOtherClass::*)(unsigned char*, int), thus the error. You need an object to call the latter, while the former is a free function.
Look at the possible solutions listed in the Boost documentation
Another possibility is that your SomeOtherClass::myCallback is private, so you do not have access to it.
Use templates:
template <class T>
class B
{
public:
typedef void (T::*TCallBackFunction)(void);
void SetCallBack(T* pCallBackClass, TCallBackFunction pCallBackFunction)
{
if(pCallBackFunction && pCallBackClass)
{
m_pCallBackFunction = pCallBackFunction;
m_pCallBackClass = pCallBackClass;
}
}
void StartCallBackFunction()
{
(pCallBackClass->(*m_pCallBackFunction))();
}
private:
TCallBackFunction m_pCallBackFunction;
T* m_pCallBackClass;
};
Such like this. And use it:
...
B<MyClass> b;
b.SetCallBack(&b, &MyClass::MyFunction);
...