Fórumok
Ritkán kell C-ben dolgoznom, leginkább mikrokontrollerek esetén, és akkor is zömében Arduino környezetben, ahol elég kényelmes String osztály érhető el.
Most azonban ESPIDF alapon kellene SVG-t generálnom, sok mérési adat megjelenítéséhez. Ehhez sok stringet kellene összefűznöm, és sprintf műveletekkel kitöltenem. Kerestem valami kényelmesebben kezelhető String osztályt, amit használhatnék, de nem találtam. Nekiállhatnék megírni, de olyan nehezen hiszem el, hogy ezt ne csinálták volna már meg ezren.
Tudtok valami kényelmesen használható C String osztályt, amit egyszerűen használhatnék? Fontos az append és az sprintf szerű formátumkezelés.
Hozzászólások
Mintha lattam volna C++-t ESPIDF-hez. Nem foglalkoztam vele igazan, mert be vagyok oltva ellene :)
Hogy string osztaly keresel C-hez, azt nem ertem...
Ez alapján simán integrálva vannak az Arduino libek, ha azt ismered, miért nem használod azt: https://medium.com/home-wireless/how-to-program-an-esp32-in-arduino-whi…
Azért, mert az ESP32 alapból elég lassú IO kezeléssel rendelkezik, nekem meg 100ns-os mintavételezésre van szükségem. Ezt egyelőre csak ESPIDF környezetben tudtam megcsinálni, de ott nem tudom az Arduino-s kódokat használni.
De a link alapján tudsz ESP IDF API-t használni Arduino API-val egy projektben.
Elmentettem, koszi!
Nem biztos, hogy egy projekten (egy "futtathato") belul kevernem. Viszont esetleg tobb taskra lehetne bontani a feladatot. Vannak idokorlatos reszek, es van, ami raer.
Ez lehetséges, de nálam pont fordított a helyzet. ESP IDF projektben kellene Arduino API-t használnom, és ez nem ment.
Arra, hogy egy magot kikapcsoljak a rendszer felügyelete alól, és csak mintavételezésre használjam, ESP IDF projektet találtam mintául.
Lehet, hogy működne a módszer Arduino projekt alapon is, de az átállást erre és tesztelést egyelőre nagyobb szopásnak érzem, mint ESP IDF alatt stringet kezelni.
Később lehet, hogy tesztelni fogom azért ezt a módszert is, mert Arduino környezetben sokkal több könyvtár elérhető.
String összefűzésre esetleg strcat egy for ciklusba téve?
A sok allokálással és a memória töredezésével van gondom, arról nem is szólva, hogy ha én írok meg valamit, abban biztos lesz még három olyan bug, amit más már leszopott. Tehát nekem valami ilyesmi felület kellene:
Persze, ha C-ben senki nem használja így a Stringeket, akkor implementálom magam, csak azt gondoltam, ez azért elég alap probléma ahhoz, hogy már sok megoldás született rá.
Beágyazott (időkritikus) rendszerben felejtsd el az allokálást/felszabadítást. Használj statikus buffert. Ha nincs elég RAM, akkor allokálással sem fog menni.
Gábor
C-ben ha sok allokálás van akkor te rontasz el valamit. A stacken kell dolgozni.
strcat(string1, string2); // Mindkettőnek "\0"-ra kell végződnie.
> Sol omnibus lucet.
Van ilyen sprintf-re is? Mármint ami maga allokál is hozzá?
Nem értem az "ilyen" szót ebben a kontextusban, hiszen a strcat nem "ilyen".
Viszont szerintem az asprintf()-et keresed.
Igen, az zavart meg, hogy az strcpy értéke is char*. De ezek szerint nem allokál.
Azonban azt hiszem az asprintf valóban jó nekem, köszönöm!
snprintf-re az általános megoldás, hogy először NULL-t adsz át a célpointer helyett, akkor az snprintf kiszámolja neked, hogy mennyi hely kell. Allokálod azt a helyet, és utána a második snprintf hívásnak már az újonnan allokált helyet adod át. Kérdés, hogy ez neked belefér-e az időkorlátba.
asprintf/vasprintf, GNU-extension.
Idővel lassú lesz, mivel
strlen(string1)
-gyel kezdődik. Jobb követni, hogy hol jár a string vége:Meg ugye az sprintf helyett jobb lenne egy snprintf, esetleg így:
+1: a standard stringműveleteket nem szerencsés hosszú string összefűzésére használni, de ha muszáj, akkor így kell.
Nem jobb lenne, hanem az kell. El kéne felejteni a buffer overflow generátor kifejezéseket.
Szerintem maradj a kályhánál. A string.h lib nagyon sztenderd, minden platformon van, nem az Arduino sajátossága, felesleges feltalálni a kereket. Ez C, ami 50+ éve fel van találva, nem Rust meg stb., ahol modern mindenfélével lehet lustulni. Igen, nem szép a printf, sprintf szintaxisa, ma már archaikusnak és hieroglifának hat, de kis gyakorlással hozzászoksz. Most még kényelmetlen, mert nem szoktál hozzá.
Esetleg ha csak SVG készítése a cél, akkor ahhoz lehet jobban járnál valami interpretált scriptnyelvvel, Python, Lua, Perl, ahol elérhető külön SVG-s modul, ha nem zavar, hogy kicsit lassabban fog futni, mint egy lefordított bináris.
“A computer is like air conditioning – it becomes useless when you open Windows.” (Linus Torvalds)
Amikor routerek fw-ét programoztam, a legnagyobb félelmünk egy esetleges underrun/overflow probléma, az invalid pointer dereferencing, illetve a memory leak volt.
Kezdetben a BSD-s fiúk féle ún. n-es függvényekkel dolgoztam. Ebben az volt a szar, hogy könyvelnem kellett a hosszokat is (vagy minden sztringműveletnél leszámoltatni), illetve nem volt automatikus újraallokáció.
Aztán mivel később más miatt is kellett glib, áttértem annak a GString típusára és függvényeire. Ez megoldja az allokációt egy köztes réteggel (valójában slice-okat allokál, és szükség esetén ezekből könyvel Neked területet, tehát nem futsz bele durva allokációs overhead-be valami szerencsétlen esetben, mert a lib ezt okosan kezeli).
De ezek x86 procis eszközök voltak, már akkor GB-os nagyságrendű memóriával. Egy ESP32-n valószínű nem ez lesz az optimális megoldás.
A másik véglet, amikor számológépre fejlesztettem C-ben (TI-89-re), ott mindent magadnak meg kellett csinálni. Amit csak lehetett, igyekeztem pointer-aritmetikával megúszni.
Nem tudom mennyire összetettek a sztringműveleteid. Ha kb. azonos substring-eket kell csak variálnod, esetleg közéjük fosni néhány értéket, akkor ezekből minél többet érdemes statikusan tárolni a memóriában (akár az egyes számjegyeket is!), és a manipuláló függvények egy ,,pointer-string"-en vagy tömbön dolgoznának.
Saját printf() implementációd pl. egy ilyen pointer-string-et kap, aminek minden szava egy pointer: kiírja az adott címen lévő string-et, \0 elérésekor ugrik a következő pointerre, és így tovább.
Amikor értékeket kell behelyettesíteni, van, hogy a leggyakoribb értékeket vagy akár az egyes számjegyeket is letárolom egy sztringben, és a pointerükkel hivatkozok rájuk. Olcsóbbra jöhet ki, mint egy ,,okos" printf() függvényt hívni, formátumsztring-feldolgozással. (HP kalkulátoroknál egyébként RPL nyelven is szokás ez: a számok talán 20-ig elérhetőek memóriacímen is, ami jóval olcsóbb, mintha értékként kellene feldobni őket a stack-re.)
Embedded hardverre - hacsak nem találsz valami nagyon jó kész lib-et - érdemes a hw sajátosságait figyelembe véve megírni néhány nagyon egyszerű elemi függvényt, és ezekre építeni. Szerintem.
Most azonban ESPIDF alapon kellene SVG-t generálnom, sok mérési adat megjelenítéséhez.
Mekkora lesz az az SVG, ami itt készül? Annak fényében, hogy a ketyerédben van kb. 300KB RAM, én úgy gondolom, hogy mondjuk olyan 20-30KB-ig vagy jó, ha ennél nagyobb lenne a fájl, akkor jön az a verzió, hogy raksz mellé egy full featured OS-t futtató gépet (mondjuk valami linuxos *Pi, sok-sok száz MB RAM-mal), oda átküldöd az adatot minimális formázással, és majd ott csinálsz belőle weboldalt.
És 20-30KB-ig pedig statikus, fix méretű pufferbe gyűjteném a fájl tartalmát.
+1 Mikrokontrolleren a sting libekkel az lesz a probléma, hogy folyton dinamikusan akarnak allokálni memóriát.
Ilyen környezetben ha csak lehet fix pufferbe kell dolgozni. Ha nem fér be a memóriába az eredmény, akkor pedig streamelni kell, ahogy előáll az eredmény egy része már küldeni is kell a célnak és újrahasznosítani a buffert.
Van egy jópofa template megoldás, ami fejlesztési időben csinál template<->forráskód konverziót: https://github.com/qgears/rtemplate#rtemplate
Ezzel csináltam már olyat, hogy mikrovezérlő állított elő hosszú generált szöveget, amit egy nyomtatóra streamelt. Ez a leghatékonyabb módja a szöveg generálásnak mind template szerkesztés, mind runtime teljesítmény szempontjából azok közül amit ismerek.
Igen, lehet, hogy nálam is ehhez kell majd folyamodni. Jelenleg 600 mintavételezést tudok begyűjteni (60us), ha az ESP generálja hozzá az SVG kiértékelést. De ha javascripttel tudnék SVG-t generálni - márpedig, ha jól látom, lehet -, akkor az ESP-nek csak be kellene gyűjteni az adatokat, és átküldeni a böngészőnek, amiben a javascript majd kiértékeli. Mivel egy mintavételezés eredménye 4 bájton tárolható, várhatóan 60000 mintát is be tudnék (6ms) gyűjteni az elemzéshez. Már, ha valami egyszerű formában, át tudok küldeni 60000 4 bájtos bináris adatot a javascript részére. Ennek még nem jártam utána.