How to pass lambda function by pointer? - c++

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

Related

Can I pass the "this" of my calling class into a lambda function?

I'm using lambda functions as callbacks.
Quickie example:
class Something
{
public:
int mValue=25;
std::function<void()> mCallbackPtr;
DoSomething()
{
mCallbackPtr(); // <- But I want "this" in the lambda function to point at
// this object, so that the code of the lambda function
// acts just like it's an extension of this function.
}
};
SomeCode()
{
Something* MyThing=new Something;
MyThing->mCallBackPtr = [=]() {cout << this->mValue;} // Since Something::DoSomething called
// this, I would like it to behave as
// if it was just an extension of
// Something. Possible?
MyThing->DoSomething();
}
So is what I have in the comments up there possible? I'm trying to make a very flexible class that I can hook lambda functions right into to extend the class without having to inherit a whole new class. I could pass "this" as an argument, but just for consistency, I'd love to be able to tell the lambda function to act like it's in scope of the calling function.
When I capture "this" it captures whatever is local where I declare the lambda function. I'm trying to capture "this" at function call time, not definition time.
Can it be done?
When I capture "this" it captures whatever is local where I declare the lambda function. I'm trying to capture "this" at function call time, not definition time.
That means, you did not capture it but you want to use it at the time you call your callback from the context of your class. Quite simply, pass "this" as parameter for your callback function!
class Something
{
public:
int mValue=25;
// Change signature for your functional object, it now takes
// a pointer to your object which is "this" at calltime.
std::function<void(Something*)> mCallbackPtr;
void DoSomething()
{
mCallbackPtr(this); // <- But I want "this" in the lambda function to point at
// this object, so that the code of the lambda function
// acts just like it's an extension of this function.
}
};
int main()
{
// no need to create object on heap, use stack.
// avoids missing delete :-)
Something MyThing;
int anyVarToCapure = 77;
MyThing.mCallbackPtr = [=](Something* obj)
{
std::cout << anyVarToCapure << std::endl;
std::cout << obj->mValue << std::endl;
};
MyThing.DoSomething();
}
Since 'this' is a c++ keyword, it has functionality that is defined by the standard, so the answer is no, you can't use the word 'this' to mean something other than what 'this' means in the context where it is used.
In the context you are using it, this can't mean anything other than what it means.
https://en.cppreference.com/w/cpp/language/this
In the context of extending a class, something like this is possible:
class animal {
public:
std::string sound{ "" };
std::function<void()> callback;
void make_sound() { callback(); }
};
// a dog, which "is an animal"
class dog : public animal {
public:
// construct, and "extend" animal by setting the callback
dog() {
// in this context, 'this' is appropriate
callback = [&]() { this->sound = "bark"; };
}
};
// a cat, which "is an animal"
class cat : public animal {
public:
// construct, and "extend" animal by setting the callback function
cat(){
// in this context, 'this' is appropriate
callback = [&]() { this->sound = "meow"; };
}
};
void make_animal_sounds() {
cat a_cat;
dog a_dog;
a_cat.make_sound();
a_dog.make_sound();
// in this context, an instance must be specified
a_cat.callback = [&]() {a_cat.sound = "quack"; };
// now a_cat will sound like a duck
a_cat.make_sound();
}
Of course there are more conventional ways of extending a class, but maybe this is what you were trying to do.

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 make work simple button class with callback?

How to make simple button class to call custom function on press. Some code example:
class Button
{
public:
Button();
Draw();
Press();
SetCallback(void(*cback)());
priate:
void (*callback)();
}
void Button::SetCallback(void(*cback)())
{
callback = cback;
}
class GameState
{
...
}
class MenuState : public GameState
{
Button *btn;
}
class Game
{
...
}
bool Game::Init()
{
std::unique_ptr<GameState> menu = std::unique_ptr<MenuState>(new MenuState);
}
void Game::PopState(){
states.pop_back();
}
How to set callback in button to Game::PopState() function in this example. I need Then I press button it call Game::PopState function.
What you're looking for is a tutorial on function pointers, which can be found here.
If you need to pass an argument, your button function pointer should either have a pointer or a reference to your Game object, as member functions require references( to which object owns the function call). If the popstate function in your Game class is private you may need to make it public or a friend function.
You should be able to modify the example below by replacing the string reference with a reference to the Game object. If you need a more generic callback look into templates(better but a bit more complicated) or type punning(generally considered bad practice)
#include <iostream>
#include <string>
class Button
{
public:
void SetCallback(void(*cback)(std::string&));
void Press(std::string str){
//Make sure some sort of check is done in order to prevent undefined behavior from a call
if(callback != nullptr)
callback(str);
}
Button(){
callback = nullptr;
}
private:
void (*callback)(std::string&);
};
void Button::SetCallback(void(*cback)(std::string&))
{
callback = cback;
}
//Method 2 for calling function
void DoStuff(std::string& str){
std::cout << str;
}
int main(void){
Button btn;
//Method 1 for calling function, replace body with Game.PopStates();
auto foo = [](std::string& str){ std::cout<<str.size();};
btn.SetCallback(foo);
btn.Press("A");
//Method 2 for calling function
btn.SetCallback(&DoStuff);
btn.Press("\nPressed Button");
return 0;
}
Your function pointer for Game should be something like this:
void SetCallback(void(*cback)(Game&));
You can call it like this:
auto foo = [](Game& g){ g.DoStuffInClass(); };
btn.SetCallback(foo);
btn.Press(game);
The above examples work fine and are usually all you need to do, but this article here goes more in-depth about member function pointers. The main takeaway from the article is typedef is another way for writing member function pointers like shown:
typedef int (Fred::*FredMemFn)(char x, float y); // Please do this!
All the above does(when implemented with PopStates), however, is lock your button callback into using void functions called by your Game objects, which limits your ability to use the button. You can use a pointer instead of a reference if you want to allow special cases for acting without a Game object, but either way your Game object has to find some way of being put in inside your callback.

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;

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.