Trying to Call Member Function in own instance

Hey everyone!

What I'm trying to do is the following: I want to be able to parse a string, and then call the function associated with that string with arguments separated by a delimiter. I think I have this part done fine, except I can't call my function instance properly in Arduino.

#include <ArduinoSTL.h>
#include
#include
#include <Adafruit_NeoPixel.h>
#include
#include
#include <EEPROM.h>
#define LED_PIN 4
#define LED_COUNT 12
#define MY_ROLE 0
//#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) //This call doesn't work in Arduino

#define X_ADDR 0
#define Y_ADDR 1
#define MY_ROLE 2

Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

class CommandHandler{
typedef void (CommandHandler::*pfunc)(std::vector&);

CommandHandler::CommandHandler(){
x = EEPROM.read(X_ADDR);
y = EEPROM.read(Y_ADDR);
role_id = MY_ROLE;
init_commands_with_args();
}
CommandHandler::CommandHandler(int x, int y, int role_id){
this->x = x;
this->y = y;
this->role_id = role_id;
init_commands_with_args();
}
public:
int x, y, role_id;
std::map<String, pfunc> commandsTable;
void set_red(){show_led_int(255,0,0);}
void set_green(){show_led_int(0,255,0);}
void set_blue(){show_led_int(0,0,255);}
void set_purple(){show_led_int(255, 0, 255);}
void set_yellow(){show_led_int(255, 255, 0);}
void set_cyan(){show_led_int(0,255,255);}
void set_white(){show_led_int(255,255,255);}
void set_none(){show_led_int(0,0,0);}

void init_commands_with_args(){
commandsTable["a"] = &show_led;
//commandsTable["b"] = &blink_color;
//commandsTable["c"] = &theaterChase;
//commandsTable["d"] = &rainbow;
//commandsTable["e"] = &theaterChaseRainbow;
return;
}

void handle_command(std::string input, std::string delimiter = "/"){
if (input.size() == 1){
switch(input[0]){
case 'R':
CommandHandler::set_red();
case 'B':
CommandHandler::set_blue();
case 'G':
CommandHandler::set_green();
case 'W':
CommandHandler::set_white();
case 'P':
CommandHandler::set_purple();
case 'C':
CommandHandler::set_cyan();
case 'Y':
CommandHandler::set_yellow();
case 'N':
CommandHandler::set_none();
}
}
else{
std::vector parses; // 10 maximum args
size_t pos = 0; size_t i = 0;
String token;
//std::string tokens = s.substr(0, s.find(delimiter));
while ((pos = input.find(delimiter)) != std::string::npos) {
token = String(input.substr(0, pos).c_str());
//std::cout << token << std::endl;
parses.push_back(token);
input.erase(0, pos + delimiter.length());
i++;
}
//Parses is now an array of strings.
pfunc cmd_func = commandsTable[parses[0]];
parses.erase(parses.begin());
((this).(*(this.cmd_func)))(parses); //This line fails no matter what I try to do. //Expected unqualified-id before '(' token
//I want to call the function of this instance that is in commandsTable, with arguments defined in the vector parses.
//The first element of the vector which is later erased is the function in commandsTable that is mapped
//Other elements are arguments in the string.
}
}
void show_led(std::vector & input){
int r = String(input[0].c_str()).toInt();
int b = String(input[1].c_str()).toInt();
int g = String(input[2].c_str()).toInt();
uint32_t mycolor = strip.Color(r, b, g);
strip.setPixelColor(0, mycolor);
strip.setPixelColor(1, mycolor);
strip.setPixelColor(2, mycolor);
strip.setPixelColor(3, mycolor);
strip.setPixelColor(4, mycolor);
strip.setPixelColor(5, mycolor);
strip.setPixelColor(6, mycolor);
strip.setPixelColor(7, mycolor);
strip.setPixelColor(8, mycolor);
strip.setPixelColor(9, mycolor);
strip.setPixelColor(10, mycolor);
strip.setPixelColor(11, mycolor);
strip.show();
}
};

The relevant snippet of this code is the following:

pfunc cmd_func = commandsTable[parses[0]];
parses.erase(parses.begin());
((this).(*(this.cmd_func)))(parses); //This line fails no matter what I try to do. //Expected unqualified-id before '(' token

I'm having issues with calling this instance's function definition. I get the above error doing multiple / different types of syntaxes to support member to function pointers. What did I do wrong?

Thanks!

sketch_feb08a.ino (9.32 KB)

sketch_feb08a.ino (9.32 KB)

Showboo:
//#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember)) //This call doesn't work in Arduino

Try:

#define CALL_MEMBER_FN(objectPtr, functPtr) ((objectPtr)->*(functPtr))()
 ((this).(*(this.cmd_func)))(parses); /

What's up with the mutil-degree indirection. You can just call the member method normally:

cmd_func(parses);

or

this->cmd_func(parses);

If you must do the weird thing:

#define CALL_MEMBER_FN(object,ptrToMember, args)  ((object).*(ptrToMember))(args)
CALL_MEMBER_FN(*this, &this->cmd_func, parses);

arduino_new:

 ((this).(*(this.cmd_func)))(parses); /

What's up with the mutil-degree indirection. You can just call the member method normally:

cmd_func(parses);

or

this->cmd_func(parses);

If you must do the weird thing:

#define CALL_MEMBER_FN(object,ptrToMember, args)  ((object).*(ptrToMember))(args)

CALL_MEMBER_FN(*this, &this->cmd_func, parses);

cmd_func(parses); //Results in the following compilation error:
"exit status 1
must use '.' or '->' to call pointer-to-member function in 'cmd_func (...)', e.g. '(... ->* cmd_func) (...)'"

Doing the CALL_MEMBER_FN and having a class-variable cmd_func, I get the following error:

exit status 1
'&((CommandHandler*)this)->CommandHandler::cmd_func' cannot be used as a member pointer, since it is of type 'void (CommandHandler::**)(std::vector&)'

I think there may be an issue with how I declared the function pointers and their type most likely. But I can't figure it out still.

Try:

CALL_MEMBER_FN(*this, this->cmd_func, parses);

That worked perfectly, thanks!

Steps in case anyone else is reading this:

  1. Make sure that your command_function is available within your class to access such that the (this) ptr can actually retrieve the var.
  2. Call it in the syntax above

So that works, now my question is, why does cmd_func (or a pointer of my function) have to be declared as a class variable, instead of just being a local variable in my handle_command function?

sketch_feb08a.ino (9.46 KB)

Because the syntax I provided assumed that "cmd_func" is a member, not local variable.

With local variable, you can just do:

CALL_MEMBER_FN(*this, cmd_func, parses);