Search code examples
c++11arduino-esp32

Calling member function by pointer


I'm developing on an ESP32 with vscode and the ESPAsyncWebServer and Wifi libraries. I'm tring to make my own wifi manager, so I'd like to put some function in a class, but I've some trouble to point to member functions.

I have this definitions without class:

void onNotFound(AsyncWebServerRequest *request){
  //Handle Unknown Request
  request->send(404);
}

String processor(const String& var)
{
  if(var == "HELLO_FROM_TEMPLATE")
    return F("Hello world!");
  return String;
}

I want to call them from a class witch is:

My_Wifi.h

class My_Wifi {
    private:
        Config *config;
        DNSServer dnsServer;
        AsyncWebServer server;
        uint16_t serverPort = 80;
        void onNotFound(AsyncWebServerRequest *request);   <------
        String processor(const String& var);   <-----
        void webServerSetup();
    public:
        My_Wifi();
        void setup(uint16_t port);
        void sendJsonDoneResponse(AsyncWebServerRequest *request);

};

My_Wifi.cpp

void My_Wifi::onNotFound(AsyncWebServerRequest *request) {...}

String My_Wifi::processor(const String& var) {...}

void My_Wifi::webServerSetup() {
  
  this->dnsServer.start(53, "*", WiFi.softAPIP());

  this->server.onNotFound(this->onNotFound);  <------

  this->server
    .serveStatic("/wifi_settings.html", SPIFFS, "/wifi_settings.html")
    .setTemplateProcessor(this->processor)    <------
    .setFilter(ON_STA_FILTER);

...
}

Obviously this it's only to call the function not to reference it.

How can I call a member function via pointer ?

Thanks for your time.

I tryed:

typedef void (My_Wifi::*onNotFoundFn)(AsyncWebServerRequest *request);

void My_Wifi::webServerSetup() {
  
  this->dnsServer.start(53, "*", WiFi.softAPIP());

  onNotFoundFn ptr = &My_Wifi::onNotFound;
  this->server.onNotFound(*ptr); //this->server.onNotFound(ptr);
  ...
}

Solution

  • In order to call member functions, you'll need to supply the object the member function is supposed to be called upon and it should match

    typedef std::function<String(const String&)> AwsTemplateProcessor;
    

    Example using a lambda, capturing this:

    .setTemplateProcessor([this](const String& str) { return processor(str); } )
    

    A similar lambda for onNotFound which should match

    typedef std::function<void(AsyncWebServerRequest *request)> ArRequestHandlerFunction;
    

    would look like this:

    server.onNotFound([this](AsyncWebServerRequest* r) { onNotFound(r); });
    

    Since you do not actually use this in your onNotFound callback, you could make your current callback function static:

    class My_Wifi {
        private:
            static void onNotFound(AsyncWebServerRequest *request);
    

    and supply that without a lambda:

    server.onNotFound(&My_Wifi::onNotFound);
    

    Alternatively, do not create a member function at all. Just supply a lambda:

    server.onNotFound([](AsyncWebServerRequest* request){ request->send(404); });