Search code examples
c++arduinorefactoringesp8266

Passing a function as a parameter within a class


So I'm trying to enlist the use of ESPAsyncWebServer for a project, and due to the size of said project I'm refactoring my code into a bunch of different libraries. This is to be part of the Client Server handling section.

I've determined how to effectively pass the *request to separate functions for the purpose of cleaning my code up. I.E. Within my Libraries .cpp file

server->on("/heap", HTTP_GET, [this](AsyncWebServerRequest *request) { handleHeap(request); });

which fires:

void CServer::handleHeap(AsyncWebServerRequest *request) { request->send(200, "text/plain", String(ESP.getFreeHeap())); }

Where I'm running into an issue is trying to pass in my "Processor" function to the response for templating.

String CServer::processor(const String &var)
{
if (var == "locationLat")
return String(gps.location.lat());
return String();
}

void CServer::handleGPS(AsyncWebServerRequest *request)
{
request->send(SPIFFS, "/gps.htm", String(), processor);
}

error: no matching function for call to 'AsyncWebServerRequest::send(fs::FS&, const char [9], String, )

Trying to pass processor() in a Lambda also doesn't compile, because there isn't a parameter going in.

error: no matching function for call to 'CServer::processor()' request->send(SPIFFS, "/gps.htm", String(), [this] { processor(); });
^ lib\CServer\CServer.cpp:128:66: note:
candidate is: lib\CServer\CServer.cpp:108:8: note: String
CServer::processor(const String&)

sooo, how do I handle passing the required processor function, into my response parameters as instructed in the guide here?

For reference:

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

// ...

//Send index.htm with template processor function
request->send(SPIFFS, "/index.htm", String(), false, processor);

Fine if its all in main.cpp, but that is not what I want to do!


Solution

  • Since your processor function is a class method, you'll need to bind it with the implicit this argument.

    We can find the callback typedef : typedef std::function<String(const String&)> AwsTemplateProcessor;

    request->send(SPIFFS, "/index.htm", String(), false, [this](const String &var) -> String { return this->processor(var); });
    

    The lambda here is taking a const String &var as parameter such as the AwsTemplateProcessor, and we precise the return type of the AwsTemplateProcessor function by writing -> String after the lambda prototype. By precising the parameters and the return type correctly the send method can relate the lambda to the std::function (AwsTemplateProcessor).