Sziasztok,
Arduino alapokon szeretnék programot írni ESP32-re. MQTT protokollra szeretnék egy objektumot készíteni, hogy minden egységbe legyen zárva.
A következő problémába futottam bele: MQTT / PubSubclient librari alkalmazása esetén vagy lehet egy callback metódust alkalmazni, ami az üzenet érkezésekor hívódik meg.
Ez azonban alap esetben nem lehetséges, ha a callback metódus sima member function. Lehet objektumon kívüli vagy static, de akkor elvesztek egy pár objektum adta lehetőséget.
Az objektum a következő:
https://pastebin.com/tT8nNvWC
Sok keresés után találtam is megoldásokat, de ezek valahogy nem működnek.
Sajnos nem vagyok egy C guru, ezért fordulok hozzátok.
Tehát a mellékelt kódból kiemelve a megoldásokat és a hibákat:
// this -> client.setCallback(callback);
// Problem: argument of type "void (Mqtt::*)(char *topic, uint8_t *payload, unsigned int length)" is incompatible with parameter of type "void (*)(char *, uint8_t *, unsigned int)"C/C++(167)
// this -> client.setCallback ( [this] (char* topic, uint8_t* payload, unsigned int length) { this->callback(topic, payload, length); });
// Problem: no suitable conversion function from "lambda []void (char *topic, uint8_t *payload, unsigned int length)->void" to "void (*)(char *, uint8_t *, unsigned int)" existsC/C++(413)
// client.setCallback(std::bind(&Mqtt::callback));
// Problem no suitable conversion function from "std::_Binder<std::_Unforced, void (Mqtt::*)(char *topic, uint8_t *payload, unsigned int length)>" to "void (*)(char *, uint8_t *, unsigned int)" existsC/C++(413)
Tudna valaki segíteni?
üdv: redman
Hozzászólások
Az elso namespace-gondnak tunik. Lehet hogy az megoldja a tobbit is.
Ez tipikus példa a rosszul megdesignolt API-ra. Ha már C módon gondolkodnak, akkor callbacknek kéne valami "void *userdata" jellegű paraméterének lennie, hogy át tudd adni az osztályod címét. Vagy használhatnának std::function-t a C fvptr helyett.
Szerintem ezzel sokat nem tudsz csinálni. Ha csak 1 példány van az osztályodból, akkor egy globális változón keresztül tudsz rá hivatkozni a callbackből. Ha több példány van, akkor valszeg nincs normális megoldás erre (esetleg, ha tudod, hogy melyik object callback-jét várod következőnek, akkor globális változóba be tudod tenni).
> akkor valszeg nincs normális megoldás erre
Dehogynem 1: Lérehozol egy rakás függvényt kódgenerátorral, annyit, hogy minden callbacknek másikat tudj adni. Berakod őket egy tömbbe, és onnan használod őket index szerint. Minden fv azzal kezdődik, hogy meghívja a generikus handlert egy indexszel. Az index alapján pedig egy tömbben eléred a hozzá tartozó ojjektumot.
Dehogynem 2: Debuggerrel megnézed, hogy mennyivel kell visszalépkedni a stacken, hogy kiolvashass valami azonosítót, hiszen a hívó program tuti, hogy tárol valahol valamit. Beteszed a mágikus konstansokat a programba, és simán kiolvasod az értéket pl így:
Két teljesen normális megoldás is van a problémára :-) Ha többet gondolkodnék talán jönne még hasonló...
Maradjunk annyiban, hogy ez eléggé szubjektív, hogy ezek a megoldások normálisak-e. Tutira nem csinálnám egyiket se. Akkor inkább már az eredeti libet módosítanám, ha jól nézem megvan a forráskódja, valszeg eléggé egyszerű beletenni egy "void *userdata" pointert a callbackbe.
Ez nagyot ütött. :)
Köszönöm, örülök, hogy nem én néztem el valamit. Megpróbálom majd a lehető legszebben megoldani
https://www.redman.hu
gyorsan atfutva es jo esetben jo repot megtalalva, ez a cucc kaphat std::function-t is
https://github.com/knolleary/pubsubclient/blob/2d228f2f862a95846c65a851…
az meg bindelheto.
ha meg megse, akkor lehet forkolni es beleirni... (vagy vki mar megtette).
Királyság, működik is.
Frissítenem kellett a library-t és definiálni a programomban az ESP32-t.
Nagyon szépen köszönöm!
https://www.redman.hu