I have object of class
class MenuItem {
public:
void updateInputText(string text)
{
this->text += text;
}
string getText() const {
return this->text;
}
void trigger(Event event)
{
switch (event) {
case ENTER:
this->onEnterAction();
break;
}
}
function<void(void)> onEnterAction;
private:
Text text;
void onEnter();
};
I create object and set event handler
MenuItem IP;
IP.onEnterAction = eventOnEnter;
// ENTER - element from enum
IP.trigger(ENTER);
Event handler:
function<void(void)> eventOnEnter = [&] () {
auto selected = next(this->currentMenu.begin(), this->selected);
selected->updateInputText("Hello");
};
And second object of MenuItem
MenuItem nextButton;
next.onEnterAction = [&] () {
Log::write("IP: " + IP.getText());
};
// ENTER - element from enum
next.trigger(ENTER);
But IP.getText() always empty. What i do wrong?
All objects created in one scope (in one function)
Whenever I see something like this
MenuItem nextButton;
next.onEnterAction = [&] () { // Should next be nextButton???
Log::write("IP: " + IP.getText());
};
// ENTER - element from enum
next.trigger(ENTER);
I'm waiting for a disaster to occur. And if you had shown a fully working example you would have noted that your example code might have worked ... so what is the problem.
The main problem is that you capture everything by reference, but from your code I can't se if it should work, but I think not in a large system, the reason is that the captured values have gone out of scope.
std::vector<MenuItem> CreateMenu() {
std::vector<MenuItem> res;
function<void(void)> eventOnEnter = [&] () {
auto selected = next(this->currentMenu.begin(), this->selected);
selected->updateInputText("Hello");
};
MenuItem IP;
IP.onEnterAction = eventOnEnter;
res.push_back(IP);
MenuItem nextButton;
nextButton.onEnterAction = [&] () {
Log::write("IP: " + IP.getText());
};
res.push_back(nextButton);
return res;
}
void Call() {
auto buttons = CreateMenu();
// what is captured at this point???
buttons.back().trigger(ENTER);
}
Most of the captured has now gone out of scope.
Surt gave me a hint... Scope.
All MenuItems pushed to vector, and when i use this function
next.onEnterAction = [&] () {
Log::write("IP: " + IP.getText());
};
I try to get text from empty variable, when i changed function to
next.onEnterAction = [&] () {
auto selectedIP = std::next(currentMenu.begin(), 0);
Log::write("IP: " + selectedIP.getText());
};
Related
void Callback (XPointer, XRecordInterceptData *pRecord) { std::cout << "my logs\n"; }
int main ()
{
if(auto* const pDisplay = XOpenDisplay(nullptr))
{
XRecordClientSpec clients = XRecordAllClients;
auto* pRange = ::XRecordAllocRange();
pRange->device_events = XRecordRange8{KeyPress, ButtonRelease};
auto context = ::XRecordCreateContext(pDisplay, 0, &clients, 1, &pRange, 1);
::XRecordEnableContextAsync(pDisplay, context, Callback, nullptr); // use with/without `...Async()`
::XRecordDisableContext(pDisplay, context);
::XRecordFreeContext(pDisplay, context);
::XFree(pRange);
::XFlush(pDisplay);
::XSync(pDisplay, true);
}
}
I am noticing that even after XRecordDisableContext(), the Callback() continues to be invoked.
How can we disable the recording, so that the callback isn't invoked anymore?
Note:
Have taken example from this site.
Don't know how to use XRecordEnableContext(), so using XRecordEnableContextAsync(). Is that the source of problem?
One way is to move below statement into the Callback() or some equivalent other thread. For testing purpose, I changed the code as below where after few event raised, I disable from the Callback() and it works.
::Display* pDisplay;
XRecordRange* pRange;
XRecordContext context;
#define CHECK(EVENT) if(*pDatum == EVENT) qDebug() << #EVENT
void Handle (XPointer, XRecordInterceptData *pRecord)
{
std::cout << "my logs\n";
static int i = 0;
if(++i < 10)
return;
::XRecordDisableContext(pDisplay, context);
::XRecordFreeContext(pDisplay, context);
::XFree(pRange);
::XFlush(pDisplay);
::XSync(pDisplay, true);
}
// other code same, except 3 variables are global and "Free"-up functions are not required
I'm trying to use a factory pattern to create different types of "State" objects. The objects are returned with a pointer (State*) but shortly after the objects are created, the values they point to disappear (go to NULL or reset to boolean "true").
The code directly below is where it goes awry, but below that is a complete code sample that compiles and runs. Additionally, I've posted pictures of the debugger values before and after the usleep() command.
I feel like it may have something to do with scope and the garbage collector, but I'm not a C++ expert by any stretch of the imagination. I would have thought my pointer would have kept my referenced object alive.
// relevant code
void execute(){
// Calling the constructor directly as an example
State directState = State("temp", false, false, false);
// Using factory pattern to create a state. Just creating the "default" state as an example
State * factoryState = StateFactory::getDefaultState();
// factoryState -> name is "Reading" in the debugger, but when I try to print it out, it's gone
// Grab the names for easy reference
const char * dName = directState.name;
const char * fName = factoryState -> name;
usleep(1000000 / 100);
// factoryState -> name .... it's vanished?
usleep(1000000 / 100);
// TODO we would run the factoryState -> execute() function here
}
// Complete code example
#include <iostream>
#include <zconf.h>
// Main generic "State" class
class State {
public:
const char * name;
bool isReadable;
bool isExecuting;
bool isFinished;
State(const char name[], bool isReadable, bool isExecuting, bool isFinished){
this -> name = name;
this -> isReadable = isReadable;
this -> isExecuting = isExecuting;
this -> isFinished = isFinished;
}
};
// An inherited class. There will be lots of these eventually
class StateReading: public State { ;
public:
StateReading():State((const char *)"Reading", true, false, false) {}
};
// Factory method that will create lots of the different states
// note that it will be returning a pointer to a "State" object
class StateFactory {
public:
static State* getDefaultState(){
StateReading defaultState = StateReading();
State* state = &defaultState;
return state;
}
};
// Runs the various "States" in a template pattern
class StateExecutor {
public:
State * state;
StateExecutor(){
StateReading stateReading = StateReading();
state = &stateReading;
}
void execute(){
// Calling the constructor directly as an example
State directState = State("temp", false, false, false);
// Using factory pattern to create a state. Just creating the "default" state as an example
State * factoryState = StateFactory::getDefaultState();
// factoryState -> name is "Reading" in the debugger, but when I try to print it out, it's gone
// Grab the names for easy reference
const char * dName = directState.name;
const char * fName = factoryState -> name;
usleep(1000000 / 100);
// factoryState -> name .... it's disappeard?
usleep(1000000 / 100);
// TODO we would run the factoryState -> execute() function here
}
};
// The actual
void loop(StateExecutor stateExecutor) {
// Run the "execute" function of whatever the current state is
// The stateExecutor actually runs the state
stateExecutor.execute();
// Slow the loop down a little. Just for effect
usleep(1000000 / 100);
}
// Simple program to recreate an event loop
int main() {
try {
StateExecutor stateExecutor = StateExecutor();
int count = 0;
do {
loop(stateExecutor);
count++;
// Arbitrarily break out of the loop after 100 events.
} while(count < 100);
} catch (std::exception& e){
std::cout << e.what() << '\n';
}
}
Here are the values directly after the factory created them. All looks good.
Gah! I called usleep() and the factoryState's name field is gone and the bools have reverted to true (cout does this as well). Black magic!
Here:
static State* getDefaultState(){
StateReading defaultState = StateReading();
State* state = &defaultState;
return state;
}
You return a pointer to defaultState. This state however is destroyed when the function returns. Using this pointer later is undefined behavior. You can declare defaultState as static, though i would rather make it a static member.
I tried do something in a cpp class and when doing the function return callback to swift.
So i do these things :
Creating this function in callbackClass.cpp
int callback::run(void (*callback)(int))
{
for (unsigned int i = 0; i < 100; i++)
{
callback(i);
}
return 0;
}
In callbackClass.hpp :
class callbackClass.hpp
{
.
.
.
public:
int run(void (*callback)(int));
};
#endif
And for header.h :
int callback(void (*callback)(int));
It's good until logging callback in Swift side:
func callbackFunc(){
callback({valueFromCallback in //call cpp function
print(valueFromCallback) //Works fine
})
}
But when try to do other stuff like :
func callbackFunc(){
var value : String!
callback({valueFromCallback in //call cpp function
value = String(valueFromCallback) //It has a problem
})
}
Xcode return this error :
A C function pointer cannot be formed from a closure that captures context
I have already seen these questions but did not help:
Swift: Pass data to a closure that captures context
How to cast self to UnsafeMutablePointer<Void> type in swift
A C function pointer cannot be formed from a closure that captures context
Eventually I realized it possible to pass 'closure' to c++ as argument
So at first I created a Closure in Swift class:
typealias closureCallback = (Int32) -> ()
Then passed it to cpp side :
In header.h
int callback(void (^closureCallback)(int));
In callbackClass.hpp :
class callbackClass.hpp
{
.
.
.
public:
int run(void (^closureCallback)(int));
};
#endif
And in callbackClass.cpp
int callback::run(void (^closureCallback)(int))
{
for (unsigned int i = 0; i < 100; i++)
{
closureCallback(i);
}
return 0;
}
At last handle it in Swift :
typealias closureCallback = (Int32) -> ()
func callbackFunc(){
var value : String!
let closureValue: closureCallback = {valueFromclosureCallback in
value = String(valueFromclosureCallback)
}
callback(closureValue) //call cpp function
}
I'm trying to create the menu in a display linked to arduino by inserting the elements inside an array like the one below in pseudo-code (javascript).
var menu = {
title: 'main menu',
item: [{
txt: 'item1',
action: function() { // function that will be performed in case such an element is activated
// my code
}
},
{
txt: 'item2',
item: [{
txt: 'item4',
action: function() {
// my code
}
},
{
txt: 'item5',
action: function() {
// my code
}
}
],
action: function() {
// my code
}
},
{
txt: 'item3',
action: function() {
// my code
}
}
]
};
Later this array will be read by a recursive function that will print the menu on the liquid crystal display.
How can i do this to arduino?
Using javascript seems like an operation at anyone's reach, but can you do the same in C / C ++?
Thanks to everyone in advance for the help!
Create a struct with an string, pointer to a function and pointers to the next and previous struct
the string is the text that will be displayed for the option, the function is the function called if the user click the item, and the pointers give you the previous and next itens if the user go up or down
example:
in the header file:
const struct item
{
const char name[16];
void (*func)(void); // Pointer to the item function
const struct item * prev; // Pointer to the previous
const struct item * next; // Pointer to the next
};
in the c file:
const struct item item_ON =
{
" 1 On",
fcn_item_turn_on,
&item_OFF,
&item_PARTIAL
};
const struct item item_PARTIAL =
{
" 2 Partial",
fcn_item_partial,
&item_ON,
&item_OFF
};
const struct item item_OFF =
{
" 3 Off",
fcn_item_turn_off,
&item_PARTIAL,
&item_ON
};
then:
void menu_show()
{
putrsXLCD((rom char *)(*ptr_item).name); // or the LCD print function in your code
}
void menu_inc() {
ptr_item = (*ptr_item).prev;
menu_show();
}
void menu_dec() {
ptr_item = (*ptr_item).next;
menu_show();
}
void menu_fwd() {
(*ptr_item).func(); // execute item function
}
don't forget to initialize the ptr_item with the first item:
ptr_item = &item_ON;
From the looks of it you are trying to create a hierarchical menu system. (As the JSON Object is not an array, but more akin to a tree.)
C++ would probably be easier to implement in because of the STL, I'm not sure on your experience but I'll give a general layout. Design-wise anyways.
#include <functional>
#include <vector>
class MenuTreeNode {
std::string title;
std::vector<MenuTreeNode> children;
std::function<void(int)> action;
public:
MenuTreeNode(const std::string& title, std::function<void(int)> action = {});
// ^ Construct the node, with the action item being optional.
// {} is just an empty function block.
/*
** You can construct with a lambda function, which are pretty useful.
*/
void addChild(MenuTreeNode&& childNode); // append a node to the child array.
void displayStuff() {
// However you display stuff to Arduino...
for (auto& child : this->children) {
child.displayStuff();
}
this->action(); // Call the action.
}
};
I hope that gives you some guidance. The older answer in C is good however doesn't allow for child items that you have in your JSON struct. This might be easier to work with IMO.
I have a question about pointers and references in C++. I am a programmer who normally programs in C# and PHP.
I have two classes (for now) which are the following.
The X/Y in Controller are continuously changing but i want them up to date in the Commands. I have multiple commands like Forward, Turn, Backward etc.
When i make the commands i give them the controller but the state (X, Y) of the controller are updating every second.
How can i fix that the controller attribute in the Commands are getting updated also every second?
class Forward : ICommand
{
Controller ctrl;
void Execute() {
int CurrentX = ctrl.X;
int CurrentY = ctrl.Y;
//Check here for the current location and calculate where he has to go.
}
}
class Controller
{
int X;
int Y;
void ExecuteCommand(ICommand command) {
command.Execute();
}
}
Main.cpp
Controller controller;
Forward cmd1 = new Forward(1, controller);
Turn cmd2 = new Turn(90, controller);
Forward cmd3 = new Forward(2, controller);
controller.Execute(cmd1);
controller.Execute(cmd2);
controller.Execute(cmd3);
I have read something about pointers and references and i think i have to use this but don't know how to use it in this situation.
(code can have some syntax errors but that's because i typed over. Everything is working further except for the updating).
If you use references rather than copy objects you can see changes.
#include <iostream>
using namespace std;
class ICommand
{
public:
virtual ~ICommand() = default;
virtual void Execute() = 0;
};
class Controller
{
public:
int X = 0;
int Y = 0;
void ExecuteCommand(ICommand & command) {
// ^-------
command.Execute();
}
};//,--- semicolons required
class Forward : public ICommand //note public
{
const int step;
Controller ctrlCopy;
Controller & ctrlReference;
public:
Forward(int step, Controller & ctrl) :
step(step),
ctrlCopy(ctrl), //this is a copy of an object
ctrlReference(ctrl) //this is a reference to an object
{
}
void Execute() {
std::cout << "copy: " << ctrlCopy.X << ", " << ctrlCopy.Y << '\n';
std::cout << " ref: " << ctrlReference.X << ", " << ctrlReference.Y << '\n';
//Check here for the current location and calculate where he has to go.
ctrlCopy.X += 10;
ctrlReference.X += 10;
}
};//<--- semicolons required
int main() {
Controller controller;
Forward cmd1(1, controller);
//Turn cmd2(90, controller); //Left for the OP to do
Forward cmd3(2, controller);
controller.ExecuteCommand(cmd1);
//controller.ExecuteCommand(cmd2);
controller.ExecuteCommand(cmd3);
//Do it again to show the copy and reference difference
std::cout << "Once more, with feeling\n";
controller.ExecuteCommand(cmd1);
controller.ExecuteCommand(cmd3);
}
Giving
copy: 0, 0
ref: 0, 0
copy: 0, 0 // [1]
ref: 10, 0 // [2]
Once more, with feeling
copy: 10, 0
ref: 20, 0
copy: 10, 0
ref: 30, 0
1 shows that the copy has X and Y of 0, while the reference shown in [2] has moved by the stated step (in controller.ExecuteCommand(cmd3))
Note, we don't need to use new to make this work (don't forget delete if you use new).
Also, void ExecuteCommand(ICommand command) now takes a reference instead otherwise the by-value copy does "slicing" (e.g. see here)