0

I'm writing a class to access global variables through string-input (serial, webinterface, telnet, etc.) on an esp32. Therefore my variableAccess class has an attribute representing the variables address and an enum specifying the datatype (to make it short only int and float are in the example code below). The variable can then be set/read by the setValue/readValue methods. During initialization the variableAccess objects are created and stored in a vector 'allVariables'

Now for my problem: I want all those variableAccess-objects to provide a handler function 'wi_handle' which can then be passed to a WebServer method, but I'm getting errors because of an 'invalid use of non-static member function'. After doing some research I now understand why 'wi_handle' has to be static, but still I'm not sure how one would implement what i have to achieve (creating a subdomain and the corresponding handler on the webinterface).

My code:

#include <vector>
#include <locale>

#ifndef WebServer
#include <WebServer.h>
#endif

#ifndef server(80)
WebServer server(80);
#endif

enum ACCESS {NONE, READ, WRITE, READWRITE};
enum DATATYPE {INT,FLT};

class Variabel_Access {
    public:
      Variabel_Access(int *varPointer, String varName, ACCESS pAccess);
      Variabel_Access(float *varPointer, String varName, ACCESS pAccess);

      long int variablePointer;
      String variableName;
      ACCESS variableAccess;
      DATATYPE datatype;

      String readValue();
      String setValue(String value);

      //WI start
      void wi_handle ();
      //WI end
};

Variabel_Access::Variabel_Access (int* varPointer, String varName, ACCESS varAccess=READWRITE) {
  variablePointer=(long int) varPointer;
  variableName=varName;
  variableAccess=varAccess;
  datatype=INT;
}
Variabel_Access::Variabel_Access (float* varPointer, String varName, ACCESS varAccess=READWRITE) {
  variablePointer=(long int) varPointer;
  variableName=varName;
  variableAccess=varAccess;
  datatype=FLT;
}

String Variabel_Access::readValue () {
  if (!(variableAccess==READ || variableAccess==READWRITE)) {
    return "ERROR: no access";
  }
  switch(datatype) {
    case INT:{
      int& i = *reinterpret_cast<int*>(variablePointer);
      return String(i);}
    case FLT:{
      float& f = *reinterpret_cast<float*>(variablePointer);
      return String(f);}
    default:{
      return "ERROR: type error";}
  }
}

String Variabel_Access::setValue (String valuestring) {
  if (!(variableAccess==WRITE || variableAccess==READWRITE)) {
    return "ERROR: no access";
  }

  String response="";
  switch(datatype) {
    case INT:{
      int value = atoi(valuestring.c_str());
      *(int*)(variablePointer)=value;
      return "done";}
    case FLT:{
      float value = atof(valuestring.c_str());
      *(float*)(variablePointer)=value;
      return "done";}
    default:{
      return "ERROR: type error";}
  }
}

void Variabel_Access::wi_handle () {
  String value=readValue();
  server.send(200, "text/plane", value);
}

std::vector<Variabel_Access> all_variables;

int integer_variable=100;
float float_variable=19.17;

void setup() {
  all_variables.push_back( Variabel_Access(  &integer_variable, "myInteger", READ) );
  all_variables.push_back( Variabel_Access(  &float_variable, "myFloat") );

  for (int i=0; i<all_variables.size();i++) {
    server.on("/"+all_variables[i].variableName, all_variables[i].wi_handle);
  }
}

void loop() {
  delay(10000);
}

Edit: webserver.on() as stated in WebServer.h:

typedef std::function<void(void)> THandlerFunction;
void on(const String &uri, THandlerFunction handler);
Sim Son
  • 261
  • 1
  • 9
  • See if you can use `std::variant` as it does most of what you want to do without employing UB (as you code does) and with much better and powerful interface. Regarding your wi_handle question - it's not clear what you want to achieve. You didn't provide MCVE and It's not clear what functions does your WebServer allow to be passed to `on`. – Dan M. Oct 11 '18 at 12:21
  • you are not passing any function pointers in your code, do you? – 463035818_is_not_a_number Oct 11 '18 at 12:22
  • Pass a lambda: `[&] { all_variables[i].wi_handle(); }` – 0x499602D2 Oct 11 '18 at 12:24
  • @DanM. I'll think about your proposal using a variant. Even though this part of my code (accessing variabels) seems to work fine I'll give it a try. I'm not firm with your breviations, what do you mean with UB and MCVE? What I want to achieve is that I can set up ubdomains on the webserver for each variable set with variableAccess. Therefore I have to pass a handler function to webserver.on() for each variableAccess object (has to be a member function in this case, I think) – Sim Son Oct 11 '18 at 12:33
  • @user463035818 I'm using webserver.on() just the way I used to, except that the handler function is a member of a class this time – Sim Son Oct 11 '18 at 12:37
  • @SimSon this `*(int*)(variablePointer)=value;` is undefined behaviour in C++. [MCVE](https://stackoverflow.com/help/mcve). For example we don't know the definition of WebServer. it might be a proper C++11 (or newer) class that can handle arbitrary functors just fine, or it might be some legacy C-with-classes construct that can only accept `void(*)(void*)` as handlers, or similar. In the latter case, static function won't give you anything, you could as well just use regular free function. – Dan M. Oct 11 '18 at 12:46
  • @0x499602D2 thanks for your proposal! At least it compiles, even though I do not understand what lambdas do, yet. – Sim Son Oct 11 '18 at 12:46
  • @SimSon I saw you edit, in you case, lambda, similar to what 0x499602D2 should work. Lambdas are very powerful tool, you should definitely learn more about them. There are a lot of good learning material on them. Some basic explanation is given in this SO question: https://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11 – Dan M. Oct 11 '18 at 12:47
  • @DanM. I always try to give MCVEs and in the arduino environment I'm working in WebServer.h is available by standard. I should have mentioned... I'll learn about lambda for sure! This solution would worth being an answer, I guess, as it solved my problem so far... Thanks a lot for your assistance, guys! – Sim Son Oct 11 '18 at 12:54

0 Answers0