Pass member function to C interface requiring callback - c++

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;

Related

Replacing a design to use capturing lambda only

I am trying to generalize a callback mechanism.
I need two things for that:
Calling it in a general matter: void call() - that I was able to manage
I mean that everyone can get a void call() function, and I can even (easily) store them in an array. They are all of the same type.
class Function{
public:
virtual void call()=0;
};
template<typename T>
class TemplatedFunction : public Function{
public:
int (T::*m_fkt)();
T* m_obj;
TemplatedFunction(T* obj, int (T::*fkt)()):m_fkt(fkt),m_obj(obj){}
// Can also set here a [&](){ f(Args...args) } that will capture the callback arguments, and call it via call(). f being the std::function created for the callback.
void call(){
(m_obj->*m_fkt)();
}
};
Set (register callback) in a general matter: here I got lost...
My callbacks are statically allocated.
I saw this great option, but my only option is using a capturing lambda.
( no bind, or tuple.. )
This option is great as I can store an array of EventHandler that basically will differ by the ID of a message I will get. Unfortunately I can't use new. (I use an in place static allocation for lambda)
class EventHandler{
public:
Function* m_func=nullptr;
template<class T>
void SetCallbackFunction(T* obj, void (T::*mem_fkt)()){
if(m_func != nullptr)
delete m_func;
m_func = new TemplatedFunction<T>(obj,mem_fkt); // can't use it.
}
void TestCallback(){
if(m_func != nullptr)
m_func->call();
}
~EventHandler(){
if(m_func != nullptr)
delete m_func;
}
};
As of my callbacks are statically allocated in advanced, containing the option to call, but not to set.
I know that there are many designs available, but I am limited to using a capturing lambda only with an std::function replacement to store it.
My goal is to pass a single type EventHandler to all my messages, without the need to template the messages, so I will be able to store them in a std::array<Msg_t>
here how I want it to look in the end:
// Statically allocated callbacks that have general `void call()`
//Function* m_func_to_run_callback1 = TemplatedFunction<> Callback1();
// Function* m_func_to_run_callback2 = TemplatedFunction<> Callback2();
int main()
{
EventHandler eh, eh1;
Foo foo; // some class
Foo2 foo2; // some other class
eh.SetCallbackFunction(&foo, &Foo::bar, m_func_to_run_callback1 ) ;
eh1.SetCallbackFunction(&foo2, &Foo2::bar2, m_func_to_run_callback1) ;
return 0;
}
I think that what I am missing is :
class Function{
public:
virtual void call()=0;
virtual void set(void*) = 0; // void* being the callback function
};

C++ invalid function type casting

I've read several topics about that kind of problem - but can't find a simple and good solution. Here is the code:
void SomeFunction() { }
class A {
public:
typedef std::function<void(void)> AFunction;
static void AMethod(AFunction f) { f(); }
};
class B {
public:
void B1Method() { }
void BCorrectCall() { A::AMethod(SomeFunction); }
void BIncorrectCall() { A::AMethod(B1Method); }
};
Problem is here void BIncorrectCall() { A::AMethod(B1Method); }, where I receive error about invalid casting. What is the simplest way to achieve that kind of behaviour? Thanks a lot for any advice!
Use a lambda:
A::AMethod([this]{B1Method();});
It doesn't matter in this case, but if you wanted to store AFunction f and use it after the call to AMethod, you'd have to ensure that the B instance (the address of which is saved in the lambda) says alive as long as you use the function.
C++17 allows you to capture *this instead, which will copy the entire B instance into lambda, but normally it's not what you want.
You could do something similar with std::bind (see the other answer), but lambdas are more flexible.
B1Method is not void(*)(void), it's void(B1::*)(void).
You may do
void BIncorrectCall() { A::AMethod(std::bind(&B1::B1Method, this)); }
};
The issue is that B::B1Method() is a non-static member function in B and, therefore, it needs to be called on an instance of B.
If the implementation of B1Method() doesn't use any non-static data member of B and it doesn't call any other non-static member function of B, then simply declaring it as static will work with your current implementation of BIncorrectCall() as you will no longer need to call B1Method() on an instance of B:
class B {
public:
static void B1Method() { } // static now
void BCorrectCall() { A::AMethod(SomeFunction); }
void BIncorrectCall() { A::AMethod(B1Method); } // no change
};
Otherwise, you have to keep an object of type B whenever you want to call B1::B1Method().
The easiest way is to make it static and so there is no this object, but if you need it (the this object), you can use lambdas:
class B {
public:
void B1Method() { }
void BCorrectCall() { A::AMethod(SomeFunction); }
void BIncorrectCall() {
std::function<void(void)> el = [&](){this->B1Method();};
A::AMethod(el);
}
};
The problem is that 'B1Method' is not a simple function - it's a class method. That means that when you call myB.B1Method(), you're actually calling 'B1Method(&myB)', effectively passing the this pointer as a hidden argument - so you can't convert M1Method to a std::function without specifying which object it should act on.
One approach that should work is using std::bind to construct a callable object from a combination of an object (class instance) and the method. Something like:
void BNowCorrectCall() { A::AMethod(std::bind(&B::B1Method, this)); }

How to pass lambda function by pointer?

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();
}

Callback function C++

I'm having a great deal of problems trying to make a callback system. I want to pass a function to another class's function to receive data.
I want ExampleClass to call SeperateThread::operate, and I want SeperateThread::operate to be able to call ExampleClass::updateNumber(int) to return a value. I've been trying for hours with various function pointers etc but can't seem to get it to work.
SeperateThread is another thread so it doesn't block the main thread that ExampleClass is running in, but when SeperateThread has done it's calculations, I need to return the value to ExampleClass.
If that makes sense? Here's a run down of what I'm trying to do. In this example, I want SeperateThread::operate to call ExampleClass::updatenumber(15);...
class ExampleClass
{
public:
ExampleClass()
{
int numberToPass = 10;
// call SeperateThread::operate and pass value and updatenumber function as pointer
thread.operate(numberToPass, *updatenumber(int number));
}
~ExampleClass();
void updatenumber(int number)
{
// Do some stuff to the number passed to this function
}
private:
SeperateThread thread;
}
class SeperateThread
{
public:
SeperateThread();
~SeperateThread();
void operate(int number, &FunctionToCallBack)
{
// Do some calculations (result 5 for example purposes)
int result = numberToPass + 5;
// Call the callback function and pass result int
FunctionToCallBack(result);
}
}
There are two issues here:
1. A Callback Function Is Not Enough
You'll need both an address for the code to call back, and the identity of the object on which the code should operate. The idiomatic C++ way to do this is to encapsulate this in an object:
class SeparateThread {
public:
class Callback {
public:
virtual void ThreadDone(int result) const = 0;
virtual ~Callback() {}
};
void operate(int number, const Callback & callback)
{
// Calculate result
callback.ThreadDone(result);
}
};
ExampleClass can then either inherit privately from SeparateThread::Callback and implement ThreadDone() or define a separate callback class:
class ExampleClassThreadCallback : public SeparateThread::Callback {
public:
ExampleClassThreadCallback(ExampleClass * obj) : fObj(obj) {}
void ThreadDone(int result) const override {
fObj.updatenumber(result);
private:
ExampleClass * fObj;
}
};
You then simply call the thread as:
thread.operate(number, ExampleClassThreadCallback(this));
2. Concurrency
In a design like this, where your class gets updated from a separate thread, you are likely to run into concurrency issues, so you'll have to design appropriate mechanisms to make sure that this updating does not cause problems.
There is something important about pointing to a class member function, you have to keep in mind that a function pointer is just a regular pointer but instead of a value it points to a function, but in a class there is a special hidden variable this which makes it tricky.
One of the main problems here is that there is no pointer to the object since that would mean that you point to a function that exists within a specific object but it doesn't it just a plain function that contains this as a parameter.
thread.operate(numberToPass, *updatenumber(int number));
Here you call a function that is in another class and overall you never pass a pointer like this, it should be just the function's name since C will recognize that you want to pass it as a pointer. Generally the workaround would be to make the function static to avoid the problem with the this pointer.
One possible workaround would be to hold onto the class object and somehow hackishly call that function where you manually pass the this of the original object ( ExampleClass ).
You didn't say much about your design, but the fact that you put the source into the same field means that these classes "know" each other so why don't you just pass the class object and call the function that way like:
class BaseClass
{
public:
BaseClass() {}
~BaseClass() {}
virtual void updatenumber(int number)=0; // pure virutal method, you MUST implement this in the subclasses!
}
class ExampleClass : public BaseClass
{
public:
ExampleClass()
{
int numberToPass = 10;
// call SeperateThread::operate and pass value and updatenumber function as pointer
thread.operate(numberToPass, this);
}
~ExampleClass();
// this is now a virtual method
void updatenumber(int number)
{
// Do some stuff to the number passed to this function
}
private:
SeperateThread thread;
}
class SeperateThread
{
public:
SeperateThread();
~SeperateThread();
void operate(int number,BaseClass* ObjectToCallBack)
{
// Do some calculations (result 5 for example purposes)
int result = numberToPass + 5;
// Call the callback function and pass result int
// Note that here that this points to the BaseClass pointer but it can be a subclass of it effectively hiding it's "unneded members" at this specific point
ObjectToCallBack->updatenumber(result);
}
}
In case you want to hide the implementation you can just use a pure virtual class and pass that type of pointer to the SeperateThread class.
Edit : updated my example to use a base class.
There is a way to pass a member of a specific class instance to another function whether in a thread or not. If the callback is a member you need to wrap it together with the class instance you want the callback to affect.
template<typename T, typename F, typename R>
struct callback
{
callback(T cthis, F func) : _this(cthis), _func(func) { }
void operator()(R result)
{
(_this->*_func)(result);
}
T _this;
F _func;
};
class SeperateThread
{
public:
SeperateThread() { }
~SeperateThread() { }
template<typename T, typename F, typename R>
void operate(int number, callback<T,F,R> cb)
{
// Do some calculations (result 5 for example purposes)
int result = number + 5;
// Call the callback function and pass result int
cb(result);
}
};
class ExampleClass
{
public:
ExampleClass()
{
int numberToPass = 10;
// call SeperateThread::operate and pass value and updatenumber function as pointer
thread.operate(numberToPass, callback<ExampleClass * const, void (ExampleClass::*)(int), int>(this, &ExampleClass::updatenumber) );
}
~ExampleClass() { }
void updatenumber(int number)
{
// Do some stuff to the number passed to this function
printf("Result is %d\n", number);
}
private:
SeperateThread thread;
};
void test()
{
ExampleClass a;
}
The above will print: Result is 15.
Please note that I did not address the synchronization issues due to multithreading.
If 'updatenumber' is called by more than one thread, and your code inside it accesses other data members, then you need to serialize it by adding a mutex lock at the beginning and unlock it before returning. Best is to use std::mutex if you have C++11 compiler, or do this within a small struct, locking in the constructor and unlocking in the destructor. Then you just create one such instance immediately on updatenumber() entry.

Class member function as callback using boost::bind and boost::function

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.