Forum: Compiler & IDEs Lambda-Funktionen vereinfachen in C++ (ESP8266, ESPAsyncWebServer)


von c++ Anfänger (Gast)


Lesenswert?

Hallo,

Ich arbeite mich derzeit in den ESPAsyncWebServer für den ESP8266 ein. 
https://github.com/me-no-dev/ESPAsyncWebServer
Allerdings habe ich noch sehr wenig Erfahrung in C++, möchte nun aber in 
einem ersten Schritt das Beispielprogramm "ESP_AsyncFSBrowser.ino" ein 
wenig klarer gliedern. 
https://github.com/me-no-dev/ESPAsyncWebServer/blob/master/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino

Die Setup-Funktion ist aus meiner Sicht zu komplex, so dass ich die 
Serverkonfiguration (server.on, server.onNotFound, server.onFileUpload, 
...) durch jeweils eine Zeile ersetze möchte.

So gelingt das für Zeile 140 recht gut, wenn ich anstelle der Zuweisung
1
  server.on("/heap", HTTP_GET, [](AsyncWebServerRequest *request){
2
    request->send(200, "text/plain", String(ESP.getFreeHeap()));
3
});
folgendes schreibe:
1
  server.on("/heap", HTTP_GET, handleHeapCmd);
  nachdem ich zuvor eine Funktion
1
void handleHeapCmd( AsyncWebServerRequest *request ) {
2
  request->send(200, "text/plain", String(ESP.getFreeHeap()));
3
}
definiert habe.

Ich kann die HEAP-Funktion dann auch noch sauber aufrufen.

Das Ganze funktioniert auch sehr sauber, wenn ich das gleiche Rezept für 
die Zeilen 146-191 anwende, und diese in eine Funktion
handleNotFound( AsyncWebServerRequest *request )
auslagere.

Wenn ich jedoch die Zeilen 192-198
1
  server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
2
    if(!index)
3
      Serial.printf("UploadStart: %s\n", filename.c_str());
4
    Serial.printf("%s", (const char*)data);
5
    if(final)
6
      Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len);
7
});
durch folgendes Konstrukt ersetze:
1
server.onFileUpload(handleFileUpload);
und die folgende Funktion dafür definiere:
1
void handleFileUpload( AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final ) {
2
  if(!index)
3
    Serial.printf("UploadStart: %s\n", filename.c_str());
4
  Serial.printf("%s", (const char*)data);
5
  if(final)
6
    Serial.printf("UploadEnd: %s (%u)\n", filename.c_str(), index+len);
7
}
lässt sich der Code zwar kompilieren, die Upload-funktion (über die 
/edit URL erreichbar), funktioniert nun nicht mehr.

Ich vermute, dass dies an den weiteren Parametern der Lambda-Funktion 
liegt, die ich nicht korrekt umgesetzt habe.

Kann mich jemand hier auf den richtigen Weg schicken?

Danke!

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

c++ Anfänger schrieb:
> Kann mich jemand hier auf den richtigen Weg schicken?

Eigentlich sollte das so funktionieren. Wenn die capture clause Deines 
Lambdas leer ist, dann kannst Du den Lambda auch durch eine freie 
Funktion ersetzen. Du solltest mal untersuchen, was genau "funktioniert 
nun nicht mehr" bedeutet.

von tictactoe (Gast)


Lesenswert?

Ich würde auf diese "Vereinfachung" verzichten. Der Compiler kann sie 
nämlich nicht mehr so gut optimieren, weil er plötzlich einen 
Funktionspointer hat. Wenn man ein Lambda übergibt, hat der Compiler 
weit mehr Information, die er zum Optimieren verwenden kann.

Eine Alternative, die ich noch in Betracht ziehen würde, weil sie den 
Funktionspointer auch vermeidet, wäre das hier:
1
server.onFileUpload([](AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final){
2
    handleFileUpload(request, filename, index, data, len, final);
3
});
kann mir aber vorstellen, dass es für deinen Geschmack nicht genug 
Vereinfachung ist. Könnte aber ein Zwischenschritt sein, um dein Problem 
einzugrenzen.

von Oliver S. (oliverso)


Lesenswert?

tictactoe schrieb:
> Der Compiler kann sie
> nämlich nicht mehr so gut optimieren,

Das macht das Projekt dann natürlich völlig unbrauchbar, gerade bei den 
super-schnellen serial.printf-Aufrufen, die da in den Funktionsrümpfen 
stehen ;)

Oliver

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.