Can anyone explain me this part of the code - c++

It is a callback function but I can't figure out how this part works
if (cb_onPress) { cb_onPress(*this); } //fire the onPress event
class Button;
typedef void (*buttonEventHandler)(Button&);
class Button {
public:
//code
private:
//code
buttonEventHandler cb_onPress;
};
void Button::process(void)
{
//code
if (cb_onPress) { cb_onPress(*this); } //fire the onPress event
}
void Button::pressHandler(buttonEventHandler handler)
{
cb_onPress = handler;
}

cb_onPress is a pointer to a function returning void and taking a Button& parameter. It could point to something like this:
void foo(Button&){ std::cout << "Foo Button!\n"; }
This line, inside a Button member function,
if (cb_onPress) { cb_onPress(*this); }
checks that the pointer to function is not null, and if so, calls it, passing the same instance of Button as parameter (that is what passing *this achieves).
Example of use:
Button b;
b.pressHandler(foo); // sets cb_onPress to point to foo
....
b.process(); // Prints "Foo Button"
although presumably the call to process happens internally, in response to a n event.

if (cb_onPress) { cb_onPress(*this); }
cb_onPress is a pointer to a function. If the pointer's a nullptr you can't call it, so the code checks it's not beforehand.
The overall supported client usage is like this:
void myButtonEventHandler(Button& b) { ...do something when pressed... };
Button button; // make a button
button.pressHandler(myButtonEventHandler);

if (cb_onPress)
checks if cb_onPress is null pointer. In other words checks if that function was defined before. If it isn't then it calls function
cb_onPress
on that object

Related

C++ List of member callback functions

I am going from C development to C++ on the STM32 platform and simply cant find a suitable solution for my problem.
Please have a look at the simplified example code attached to this post.
#include <iostream>
#include <functional>
#include <list>
using namespace std;
class Pipeline {
public:
std::list<std::function<void(Pipeline*)>> handlers;
//add handler to list --> works fine
void addHandler(std::function<void(Pipeline*)> handler) {
this->handlers.push_front(handler);
}
void ethernetCallback(void) {
//handle received data and notify all callback subscriptions --> still works fine
// this callback function is normally sitting in a child class of Pipeline
int len = handlers.size();
for (auto const &handler : this->handlers) {
handler(this);
}
}
void removeHandler(std::function<void(Pipeline*)> handler) {
// Here starts the problem. I can not use handlers.remove(handler) here to
// unregister the callback function. I understood why I can't do that,
// but I don't know another way of coding the given situation.
}
};
class Engine {
public:
void callback(Pipeline *p) {
// Gets called when new data arrives
cout<<"I've been called.";
}
void assignPipelineToEngine(Pipeline *p) {
p->addHandler(std::bind(&Engine::callback, this, std::placeholders::_1));
}
};
int main()
{
Engine *e = new Engine();
Pipeline *p = new Pipeline();
e->assignPipelineToEngine(p);
// the ethernet callback function would be called by LWIP if new udp data is available
// calling from here for demo purposes only
p->ethernetCallback();
return 0;
}
The idea is that when the class "Pipeline" receives new data over ethernet, it informs all registered callback functions by calling a method. The callback functions are stored in a std::list. Everything works fine till here, but the problem with this approach is that I can't remove the callback functions from the list, which is required for the project.
I know why I can't simply remove the callback function pointers from the list, but I don't know another approach at the moment.
Probably anybody could give me a hint where I could have a look for solving this problem. All resources I've researched don't really show my specific case.
Thank you all in advance for your support! :)
One option would be to have addHandler return some sort of identifier that can later be passed to removeHandler. For example:
class Pipeline {
public:
std::map<int, std::function<void(Pipeline*)>> handlers;
int nextId = 0;
//add handler to list --> works fine
void addHandler(std::function<void(Pipeline*)> handler) {
handlers[nextId++] = handler;
}
void ethernetCallback(void) {
for (auto const& entry : handlers) {
entry.second(this);
}
}
void removeHandler(int handlerToken) {
handlers.erase(handlerToken);
}
};
class Engine {
public:
void callback(Pipeline *p) {
// Gets called when new data arrives
cout<<"I've been called.";
}
void assignPipelineToEngine(Pipeline *p) {
handlerToken = p->addHandler(
std::bind(
&Engine::callback,
this,
std::placeholders::_1
)
);
}
void unregisterPipelineFromEngine(Pipeline *p) {
p->removeHandler(handlerToken);
}
private:
int handlerToken;
};
Perhaps you could attach an ID to each handler. Very crude variant would just use this address as an ID if you have at most one callback per instance.
#include <functional>
#include <iostream>
#include <list>
using namespace std;
class Pipeline {
public:
using ID_t = void *; // Or use integer-based one...
struct Handler {
std::function<void(Pipeline *)> callback;
ID_t id;
// Not necessary for emplace_front since C++20 due to agreggate ctor
// being considered.
Handler(std::function<void(Pipeline *)> callback, ID_t id)
: callback(std::move(callback)), id(id) {}
};
std::list<Handler> handlers;
// add handler to list --> works fine
void addHandler(std::function<void(Pipeline *)> handler, ID_t id) {
this->handlers.emplace_front(std::move(handler), id);
}
void ethernetCallback(void) {
// handle received data and notify all callback subscriptions --> still
// works fine
// this callback function is normally sitting in a child class of
// Pipeline
int len = handlers.size();
for (auto const &handler : this->handlers) {
handler.callback(this);
}
}
void removeHandler(ID_t id) {
handlers.remove_if([id = id](const Handler &h) { return h.id == id; });
}
};
class Engine {
public:
void callback(Pipeline *p) {
// Gets called when new data arrives
cout << "I've been called.";
}
void assignPipelineToEngine(Pipeline *p) {
//p->addHandler(std::bind(&Engine::callback, this, std::placeholders::_1), this);
//Or with a lambda
p->addHandler([this](Pipeline*p){this->callback(p);},this);
}
void removePipelineFromEngine(Pipeline *p) { p->removeHandler(this); }
};
int main() {
Engine *e = new Engine();
Pipeline *p = new Pipeline();
e->assignPipelineToEngine(p);
// the ethernet callback function would be called by LWIP if new udp data is
// available calling from here for demo purposes only
p->ethernetCallback();
return 0;
}
You might also consider std::map<ID_t,std::function<...>> instead of list, not sure how memory/performance constrained you are.
Obligatory: do not use new, use std::unique_ptr, or better use automatic storage whenever you can. Although in this case a pointer is appropriate for e as you need stable address due to this capture/bind/ID.
std::functions are not comparable as there isn't a good generic way how to define this comparison.

Function Pointer With Vector

I'm new in C++. I'm trying to do clickable button with OpenGL. I work for add callback function for each button for 2 days, I tried many methods I found but I can't do this. My below codes are giving memory error. Where is my mistake?
main.h
#include <vector>
class Button {
public:
// Storage Vector
static std::vector<Button> Buttons;
// typedef Function
typedef void (*pointerFunction)();
// Constructor
Button(/*Parameters*/);
// Setting Callback
void setCallBack(void(*function)());
// Callback pointer
pointerFunction callback;
int value{ 4 };
};
main.cpp
#include <iostream>
#include "main.h"
std::vector<Button> Button::Buttons;
Button::Button(/*Parameters*/) {
// ...
Button::Buttons.push_back(*this);
}
void Button::setCallBack(void(*function)()) {
this->callback = function;
this->callback(); // Here is work!
}
void testFunction() {
std::cout << "Test\n";
}
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
int main() {
createMember();
for (Button& button : Button::Buttons) {
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
return 0;
}
Within this function
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
there are two things that are being doing. The first one is creating the local object classMember. The called construcfor pushes a copy of the object inside the vector Buttons. The data member callback of the copy was not initialized.
It is the data member callback of the .local object classMember that was initialized after its copy was pushed on the vector.
Rewrite the function at least like
void createMember() {
Button classMember;
Button::Buttons.back().setCallBack(&testFunction);
}
You should initialize all data members for example using in particular the literal nullptr if a corresponding initializer was not explicitly supplied. In this case you will be able to check whether a data member of a pointer type is equal to nullptr or stores an actual value.
Your createMember function don't work as you expect.
void createMember() {
Button classMember;
classMember.setCallBack(&testFunction);
}
Creates a local object that will be destroyed at function exit.
You can do it like this (though I don't think it is a good solution.)
Button & createMember() {
static Button classMember;
classMember.setCallBack(&testFunction);
return classMemeber;
}
A better solution:
std::vector<Button> Button::Buttons;
int main() {
Button b;
for (Button& button : Button::Buttons) {
button.setCallBack(testFunction);
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
return 0;
}
Note that you have to defile Button::Buttons somewhere as it is a static member This was correct in your code, I overlooked it.
And, to add at least a Button, you have to create one to be added to the vector.
Ouput:
Test
4Test
You are calling testFunction twice, at setCallBack and in the loop.
(I've added a newline.)
If as the createMember function name suggest, you want to call that to create each new element, you could pass the function pointer in constructor. If it is trivially copyable like is in your example (no pointers or resource allocation in the class) you can just create the instance and the vector copy will be fine.
Button::Button(pointerFunction f) : callback (f) {
// ...
Button::Buttons.push_back(*this);
}
void createMember() {
Button classMember (testFunction);
}
int main() {
createMember ();
for (Button& button : Button::Buttons) {
std::cout << button.value; // I can access this value.
button.callback(); // But here is give memory error!
}
}
I don't think this is a good design for anything real, though.
Your mistake is that you create a local object, push the copy of it into the vector, put the callback address to the original object, and then destroy the original object. Well, you can put the callback address as the constructor argument, then the copy would have it.
// Constructor
Button(void(*function)(), /*Parameters*/) : callback{function} {
Button::Buttons.push_back(*this);
}
But I would recommend to add a static function to the Button class which is responsible for creation a Button object and returning reference to it. This is also eliminate unnecessary creation/deletion of temporary objects.
#include <iostream>
#include <vector>
class Button {
public:
// Storage Vector
static std::vector<Button> Buttons;
// typedef Function
typedef void (*pointerFunction)();
// Constructor
Button(/*Parameters*/);
// Setting Callback
void setCallBack(void(*function)());
// Callback pointer
pointerFunction callback;
template<class... U>
static Button& createButton(U&&... u) {
return Buttons.emplace_back(std::forward<U>(u)...);
}
int value{ 4 };
};
std::vector<Button> Button::Buttons;
Button::Button(/*Parameters*/) {
// ...
Button::Buttons.push_back(*this);
}
void Button::setCallBack(void(*function)()) {
this->callback = function;
this->callback(); // Here is work!
}
void testFunction() {
std::cout << "Test\n";
}
void createMember() {
auto &classMember = Button::createButton(/**/);
//Button classMember;
classMember.setCallBack(&testFunction);
}
int main() {
createMember();
for (Button& button : Button::Buttons) {
std::cout << button.value;
button.callback();
}
return 0;
}

Passing a function name to an event class in an event bus system

I'm writing a simple event bus system to get familiar with this model. I have an addEvent function which takes an event name (string) and a function. I'm having trouble establishing my event class.
// Event class to define our event
class Event
{
public:
// function is some function that needs to be executed later
Event(const string eventName, void * function)
{
msgEvent.first = event;
msgEvent.second = function;
}
string getEvent(){
return msgEvent;
}
private:
pair<string, void*> msgEvent;
};
so when I make a call addEvent("open", openFunction), I would like to store this information as part of an Event.
I'm having a hard time understanding how I can store the function and if I'm correctly passing a function in the constructor as a parameter.
You can use function pointers or std::function. void* is for sure not correct. In any case, you need to know what signature your function has. Let's say, your functions do not take any input and do not return. Then, their signature is void()
Then, you can use the following code:
#include<functional>
#include<string>
class Event
{
public:
// function is some function that needs to be executed later
Event(const std::string eventName, std::function<void()> functionName)
{
msgEvent.first = eventName;
msgEvent.second = functionName;
}
std::string getEvent(){
return msgEvent.first;
}
void execute() {
msgEvent.second();
}
private:
std::pair< std::string, std::function<void()> > msgEvent; // why are you using
// std::pair here?
};
Now, you can write
Event myEvent( "open", [](){ /* do something */ } );
myEvent.execute();

c++ - Pointer to "unknown" class

I wrote a special class which checks some states of some external stuff and if something changes I would like to call a callback function.
These function should be not only a global function instead of a function of a special class.
To show what I mean here is some code:
void myClass::addCallbackFunction(unsigned int key, TheSpecialClass* obj, void (TheSpecialClass::*func)(unsigned int, bool)) {
if(!obj) {
return;
}
callbackFunction cbf;
cbf.object = obj;
cbf.func = func;
if(!(callbackFunctions.find(key) == callbackFunctions.end())) {
//Key allready exists.
callbackFunctions[key].push_back(cbf);
} else {
//Key does not exists at the moment. Just create it.
vector<callbackFunction> v;
v.push_back(cbf);
callbackFunctions.insert({key, v});
}
}
void MyClass::callCallbackFunction(unsigned int key, bool newValue) {
vector<callbackFunction> cbfs;
//hasKey..
if(!(callbackFunctions.find(key) == callbackFunctions.end())) {
cbfs = callbackFunctions[key];
}
//calling every function which should be called on a state change.
for(vector<callbackFunction>::iterator it = cbfs.begin(); it != cbfs.end(); ++it) {
((it->object)->*(it->func))(key, newValue);
}
}
//to show the struct and the used map
struct callbackFunction {
TheSpecialClass* object;
void (TheSpecialClass::*func)(unsigned int, bool) ;
};
map<unsigned int, vector<callbackFunction> > callbackFunctions;
Now I want to make 'TheSpecialClass' to some kind of Pointer to a class which can variate. I found void-Pointer but then I have to know which class I passed. I thought there is something like the function pointer out there which I did not found yet.
Do someone know a solution?
I used boost::signal2 to match my usecase.
A tutorial for boost::signal2 is found here.
The signals whould only call functions. Not functions on a special object. There is a workaround by using boost::bind() like:
boost::bind(boost::mem_fn(&SpecialClass::memberFunctionOfTheClass), PointerToTheObjectOfSepcialClass, _1)
The _1 is a placeholder which creates a function (reference) which requires one argument. You can add some more placeholders to use more arguments.

A stack of function pointers: how to call the function?

I have a stack of function pointers (all of void type & with no parameters). I am having difficulty finding out how I then call/execute a function that is in the stack?
If you look at the simple example below everthing compiles & works except for the last line
typedef class InstructionScreen;
typedef void (InstructionScreen::*MemberFuncPtr)();
stack <MemberFuncPtr> instructionStep; // This is how I declare it. Works
instructionStep.push( &InstructionScreen::step1 ); // This is how I add the member function step(). Works
(*instructionStep.top())(); // How do I call the function now? This doesn't work
This is the whole code I am attempting to get to compile:
class InstructionScreen
{
public:
InstructionScreen()
{
instructionStep.push( &InstructionScreen::step1 );
instructionStep.push( &InstructionScreen::step2 );
// add timer to call run instructions each 10 seconds
}
void step1()
{
}
void step2()
{
}
void runInstructions()
{
if ( !instructionStep.empty() )
{
*(instructionStep.top())();
instructionStep.pop();
}
// else kill timer
}
private:
stack <MemberFuncPtr> instructionStep;
};
You need an instance to call a member function. Try this:
InstructionScreen screen;
MemberFuncPtr step = instructionStep.top();
(screen.*step)();
To run a function in the stack from within another member function, you can use:
MemberFuncPtr step = instructionStep.top();
(this->*step)();