C/C++

SMGUI frissítés

Fórumok

Emlékeztetőül, MIT licenszű, Szabad és Nyílt forráskódú, ANSI C-ben írt, single header lib UI toolkit többféle backenddel és konfigurálható modulokkal:

SMGUI

Kicsit frissítettem monstanában, akit érdekel:
- atrex66 kolléga unszolására (és ezer hála a tesztelésért) lett Linux framebuffer backend támogatás 32 bit, 16 bit és 15 bites pixelekkel
- a fájlválasztó nem szűri a könyvtárakat, csak a fájlokat, ha van megadva kiterjesztésszűrés
- a könyvtárlétrehozást újraírtam, most a listában jelenik meg neki a névbeviteli mező, nem a keresés mezőben
- táblázat akkor is megjelenik, ha az adata NULL pointer (igaz, üresen, de legalább megjelenik)
- táblázat fejléce külön igazítható (UI_LEFT, UI_CENTER és UI_RIGHT), nemcsak az adatoszlop
- táblázat fejlécének megadható egyetlen UNICODE karakter (pl. U+02706, telefon ikon), nemcsak lefordított szöveg
- gomboknál külön állítható a felső és alsó árnyék színe (és külön ki-be kapcsolható)
- Windows-os fordításnál rendesen kezeli az "%ll"-t
- az SDL backend átírva, hogy működjön továbbra is az SDL2 és ugyanakkor a legfrissebb SDL3 alatt is (volt pár breaking módosítása Samnek).
- meg még egy csomó pici javítás, pár pixel itt meg ott, ilyenek
- a dokumentáció is frissítve lett.

Egy par linkeleses tema/kerdes

Fórumok

Ket apro, valojaban nem eletbevago de (talan) erdekes kerdes merult fel, GCC toolchainnel valo jatszadozas soran.

Az egyik a reszleges linkelessel kapcsolatos. Tegyuk fel hogy van egy forras, van benne nehany fuggveny, pl igy:

int funct1(int x)
{
 return(2*x);
}
int funct2(int y)
{
 return(y+10);
}
int entry(int z)
{
 int c;
 c=0;
 while ( 1 )
  {  sleep(1);
     printf("%d\n",funct2(c));
     c++;
  }
}

Ezt leforditjuk `gcc -ffunction-sections -fdata-sections` modon. A *.o-ban igy lesz a fentieknek megfeleloen harom .text jellegu section (.text.funct1, .text.funct2, .text.entry). Ebbol `ld -r|--relocatable` modon csinalnek egy masok objectet, ugy hogy a 

SECTIONS
{
 .text :
  {     *(.text.* .text)
  }
}

linker scriptnek megfeleloen osszevonom a .text.* section-okat egyetlenegy darab .text section-ba. Ez szuper, el is keszul a *.o/*.elf, minden oke. Viszont a fenti peldaban a funct1()-et nem hivja meg senki, igy szeretnek egy olyan *.o-t (is) amben ez nincs benne. Ha a sima teljes erteku linkelesnek megszokott modon megadom a --gc-sections opciot, akkor az hianyol egy entry-t, ertheto okokbol. Megadon --entry-nek az entry()-t. Igy lefut a reszleges linkeles, lesz is egy darab .text section, de a funct1 az meg mindig benne marad. Probalkoztam KEEP()-ekkel meg ENTRY()-kel a *.lds linker szkriptben is, de az sem segit. Barmi otlet?  (( A fenti eljaras nem csak veletlenul hasonlit arra, ahogy a linux kernel modulok, a *.ko-k keszulnek. ))

A masik kerdes meg arrol szol(na), hogyha van egy nagyobb forras, van benne egy fuggveny, amit nehanyszor meghivnak akkor az a teljes forditas + linkeles soran elfordul(hat) hogy a vegso *.elf-bol eltunik, mert az optimalizcio mindenfele inline-ositas miatt a garbage collector a vegen egyszeruen kiszedi azt a section-t. Az teljesen oke. Van-e valami __attribute__ vagy barmi hasonlo amit meg lehet adni hogy ez a fuggveny az legyen "exportalva", azaz kesobbiekben hivhato legyen? A noinline az talan jo is lehetne, de valojaban nem azt akarom (es ugy latom hogy az nem is oldja meg ezt a problemat). Szoval felolem lehet inline ha az ugy jobb/gyrosabb/kisebb (-Ox-tol fuggoen), de maradjon meg a fuggveny a vegso ELF-ben (aztan meg emiatt a vegso binary/hex image-ben).

Thx, A.

[MEGOLDVA] Kis github segítséget kérnék

Fórumok

Szeretnék egy kis segítséget kérni egy olyan HUP-os fórumtárstól, akinek van github accountja. Én sajnos nem tudok belépni, különben megcsinálnám magam (egész pontosan identification kódot kér, de az azt tartalmazó email sehogy nem akar megérkezni már egy ideje).

Szóval arról lenne szó, hogy
1. klónozni kéne a mapeditor repót
2. bemásolni az src könyvtárat ebből a repóból (a repó README-jét hagyd ki)
3. beküldeni az eredményt PR-ként nekik.

Ez egy új fájlformátum exportot ad a Tiled-hez, ami a lehető legfaékebb egyszerűségű: egy fix méretű, 16 bájtos fejléc és tömörítetlenül a tile id-k 2 bájtonként, oszt ennyi. Rengeteg alkalmazásnak nem is kell ennél több, nincs szükségük a variálható property-kre és egyébként is iszonyat macerás TMX-t betölteni (a Tiled alapértelmezett formátuma XML alapú agymenés). Ellenben ez a bináris térkép formátum teljesen dependency mentes, gyakorlatilag parszeolni sem kell, csak belapátolni a memóriába és kész is.

(ps: a formátumot implementáltam extension-ként is, de abban nagyon nem bízok, valahogy nem akarnak stimmelni a tile id-k a C++-ban lekért tile id-kkal, ezért lenne jobb, ha lefordított pluginként is elérhető lenne.)

C++ vector

Fórumok

Arduino-ban mi a különbség?

 

1) std::vector<String> cmd(1);

2) String data[500];

 

Első esetben dinamikusan nő a tömb cmd.push_back(""); utasítással a program elején, később nem változik.

A második esetben lehet az első változó a data[328] lesz, ehhez jobb a vector data.resize(329); , vagy inkább a String data[500]; a helyes megoldás?

Ezt a vektor izét nem ismerem, nem találtam hozzá számomra érthető leírást.

Ne ChatGPT-t, nem jött be.

Köszönöm a rám fordított időt a válaszolónak.

C++ #include ram probléma [MEGOLDVA]

Fórumok

https://github.com/earlephilhower/ESP8266Audio könyvtárat szeretném használni, de ez bootoláskor dől el hogy tényleg kell-e.

Ha csak #include "AudioFileSourceSPIFFS.h" van a kódban, semmi más, akkor is megeszik vagy 10kb ramot. Átnéztem de nem találom a bűnöst.

Egy extern boolt szeretnék beletenni, ha az false, felejtse el az egész projektet, de arra se jövök rá hogy hova tűnik a ram.

THX!

[Megoldva] Nem blokkolós I/O

Fórumok

Van nekem Linuxon egy /dev/ttyACM0 karakter eszközfile-om (USB CDC). Szeretném olvasni, de nem blokkolósan. Tehát azt szeretném, hogy a karakter olvasása ne akkor térjen vissza hozzám, ha van olvasható karakter, hanem akkor is, ha nincs, s akkor tudjam, hogy az nincs. Ennélfogva tudjak rá timeout-ot csinálni.

Próbáltam így:

c = fgetc_unlocked(dfd);

Ez vagy nem az, ami nekem kell, vagy nem tudom, hogyan kell használni, de ez is megvárja alapesetben, amíg jön egy karakter. Hogyan kell ezt csinálni? Mi kell nekem? poll(), epoll(), select()? Esetleg 

fcntl(fileno(dfd), F_SETFL, O_NONBLOCK);

vagy mi a megoldás?

A megoldás a poll() és read() használata lett.
 

[Megoldva] warning: Unsequenced modification and access to 'j'

Fórumok

Na, de miért?

while (isupper((unsigned char) p[j])) buff[j++] = p[j];

Az '=' operátor right to left asszociatív. Vagy dönthet a fordító úgy, hogy a magasabb precedenciájú kifejezéseket akármilyen sorrendben értékelteti ki futásidőben, s majd a részeredmények felhasználásával lesz az értékadás jobbról balra? Mert én úgy gondoltam, amikor ezt a sort leírtam, hogy előbb meghatározza p[j] értékét, majd utána ezt értékül adja buff[j]-nek, majd j-t növeli eggyel.

Ezt a warningot egyébként a Qt Creator zúdítja rám. Miért nem mcedit-tel írom a forráskódot? Akkor boldog tudatlanságban élhetnék... :)

Megoldásnak gondoltam korábban. Illetve megkerestem szemmelveréssel - eltartott egy darabig, amíg végignéztem a

grep -anF '++' *.[ch] | less

eredményeit. Egyetlen helyen használtam ezt a csúnya megoldást. Kijavítottam. Már úgy értem, abban a kódban, amelyikben szólt a Qt Creator mögött lévő analizátor, a nyitóban idézett volt az egyetlen ilyen, de van egy sokkal fontosabb kód, amiből termék lesz, abban nem szeretnék bugot. Abban volt egy ilyen csúnyaság.

Jobban megoldás. :)
 

QOI 2.0

Fórumok

Egy kis újabb csemege a bitpornó kedvelőinek :-)

Nem tudom, hányan ismeritek a Quite OK Image képformátumot. A lényege, hogy eszeveszettül faék egyszerű, mégis egész jó tömörítési rátát képes produkálni (a honlapja mondjuk hazudik, speciálisan kézzel összeválogatott képen demózza). Viszont volt benne pár dolog, ami mindig is zavart (például hogy nem képes transzparens képeket tömöríteni), ezért feltúrbóztam kicsit:

QOI 2.0

Fícsörök:
- ugyanúgy egyetlen függőség nélküli fejlécfájl, mint az elődje (kb. 200 SLoC a kicsomagoló-becsomagoló együtt)
- ugyanúgy MIT licenszű, Szabad és Nyílt Forráskódú
- azonban ez sokkal gyorsabb, pláne nagy képek esetén
- ráadásul sokkal jobban tömörít (különösen anti-aliasolt képeket)

A sebességnövekedés amiatt van, hogy mutatókat és switch/case-t használ bájttömbindexek és if/else blokkok helyett, egyébként ugyanaz a logika, nincs benne semmi trükk. A jobb tömörítési rátát pedig úgy éri el, hogy okosabban osztja ki a biteket, a legtöbb utasítás ugyanaz, de a futásidejű tömörítésre van egy hosszabb futamot is tárolni képes opció, a differencál utasításoknál van egy olyan, ami alfát és nagyobb tartományt képes leírni, a teljes csatornát tároló utasítás pedig csak a megváltozott csatornákat tárolja az összes helyett. Röviden.

Beágyazott WebAssembly futtatása

Fórumok

Tegyük fel, hogy felmerül az igény a ~-ra, azaz hogy egy programból kell tudnunk hívni WASM eljárásokat, és vice-versa, azoknak is kell hívniuk a mi natív függvényeinket. Na erre nem találtam épkézláb megoldást.
- Az egyik ilyen a wasm-micro-runtime, de hogy ez mennyire szar, azt semmi sem szemlélteni jobban, minthogy félezer fájl, 9 MEGA az nekik "micro"... Hát nekem hányadék bloatware.
- Ott volt aztán még a wasm3, ami méretét tekintve már inkább elfogadható, viszont agyfasz az API-ja, és sajnos nincs már karbantartva, mert a fejlesztőjének a házát szarrábombázták a ruszkik.
- Van még a Linux kernelbe ágyazható cervus, szintén elhalt, 7 éve bottal sem piszkálták, pedig nyitott jegyek vannak rajta.
- ...stb.

És akkor ott van még az is, hogy ezek egyike sem biztonságos, mert ezekkel BÁRMILYEN dll / so dinamikusan betölthető és futtatható, így a beágyazó programnak esélye sincs kordában tartani a benne futó szkriptet. Szóval nem az igazi.

Egy szónak is száz a vége, már megint az lett, hogy megírtam a libet magamnak, mert amit mindenki más használ, az nekem nem tetszik. Hát, ez van.

https://gitlab.com/bztsrc/wa

Előnyei:
- ha az első a micro, na akkor ez nano, merthogy 9.5 Mega helyett csak 116 Kilobájt az egész (kb. 1900 SLoC)
- mégis megvalósítja a teljes WASM MVP (Minimal Viable Product) szabványt
- egyetlen függőségmentes ANSI C / C++ fejlécfájl (na jó, libm kell neki, de a WA_NOLIBM define kikapcsol két utasítást és úgy már tényleg csak compiler built-inek elegek)
- pofonegyszerűen használható, faék egyszerű az API-ja
- maximális kontroll afelett, hogy mit csinálhatnak a szkriptek (mennyi memóriát foglalhatnak, milyen függvényeket hívhatnak stb.)
- bound check és hasonló nyalánságok (futás idejű típusellenőrzésen kívül szinte minden)
- baromi gyors, a többihez képest lobog a hajad tőle (két okból: bulk memóriafoglalás kev;s bufferre; és az értelmetlen típusellenőrzés helyett (ami O(N)) csak az elemszámot ellenőrzni (ami O(1))
- a többi megoldás memóriaigényének 10%-val is beéri (nem, nem írtam el, ugyanazt a wasm modult futtatni tized annyi memóriát fogyaszt)
- a többivel ellentétben memleak mentes (ez ráadásul garantált, mivel nem foglalgat agyba-főbe kis memóriablokkokat, hanem mindössze egy fél maréknyi buffert használ)
- nem támogat semmiféle emscripten, WASI meg hasonló 3rd party baromságot, így a szkript nem tud kitörni a sandboxából. Nincs mivel.
- fordítható debugger támogatással, példa wadbg debugger GUI applikáció is van hozzá, ennek demonstrálására (kicsi SDL-es, portolható cucc).

Példa használatra:

/* függvénykönyvtár behúzása, stb módra, nem kell linkelni semmivel */
#define WA_IMPLEMENTATION
#include "wa.h"

/* wasm bináris bitkolbásza, fordította "Clang --target=wasm32", yours truly */
uint8_t wasmbinary[1234] = { ... };

/* futás idejű linkelő tábla és kontextus */
RTLink link[] = {
    /* név       ki       be  proto */
    { "malloc",  &malloc,  0, WA_ll },  /* host -> WASM */
    { "realloc", &realloc, 0, WA_lll }, /* host -> WASM */
    { "free",    &free,    0, WA_vl },  /* host -> WASM */
    { "add",     NULL,    -1, WA_fff }, /* WASM -> host */
    { "sub",     NULL,    -1, WA_fff }, /* WASM -> host */
    { "globvar", &globvar, 0, WA_i },   /* megosztott változó */
    { 0 }
};
Module m;

/* betöltés, inicializálás */
wa_init(&m, wasmbinary, 1234, link);

/* egy WASM függvény hívása C-ből. Elöször kikeressük a szimbólumot (ha nem felejtettük el,
   hogy a link[] tömb hányadik sora, akkor keresgélés helyett csak simán O(1) lekérés) */
int addfunc = cavinton_klub? wa_sym(&m, "add") : link[3].fidx;

/* bemeneti paraméterek átadása és hívás */
wa_push_f32(&m, 1.0);
wa_push_f32(&m, 2.0);
ret = wa_call(&m, addfunc);
printf("Eztetet adta vissza: %f\n", ret.f32);

/* többet nincs mit elmondani, kérem kapcsoljaki */
wa_free(&m);

Ennyi. Ennél faékebb egyszerűségű és könnyebben integráható API-t nem bírtam kiagyalni. Négy függvény init / push / call / free és kész (oké, a push-ból van több változat, mindenféle típushoz, de akkor is 12 függvény cakk-um-pakk). A valós idejű linkelés meg egy struct tömbbel zajlik, aminek négy mezője van:
- első a szimbólum (UTF-8 sztring)
- második egy memóriacím, ezt te adod meg akkor, ha a WASM-nek akarod átadni
- harmadik egy függvényindex, ezeket meg a WASM adja meg, hogy meg tudd hívni
- negyedik meg egy prototípust kódoló bitmaszk

Bármelyik globális WASM változó láthatóvá tehető host oldalon, ha felvesszük a táblába a WASM szimbólum nevét egy host memóriacímmel. Másik irány is működik, ekkor "extern"-nek kell definiálni a WASM modulban.

De ami biztonság szempontjából nagyon fontos, a WASM szkript nem tud semmi mást meghívni, csak azokat, amik szerepelnek a listán.
Viszont ott bármilyen függvénnyel működik, de azért lehetőség van saját dispatcher megadására is egy WA_DISPATCH define-nal.

Szabad és Nyílt Forráskódú, licensze a megengedő MIT.

ld: warning: main.elf has a LOAD segment with RWX permissions

Fórumok

Egy FPGA-s projekt kapcsan futottam bele a fenti uzenetbe. A kontextus: sima C kod forditasa beagyazott kornyezetben. A limitaciok miatt a teljes zubehor, init-estul, text-estul, rodata+data+bss-estul egyetlen RAM blokkba kerul, onnan is fut, azaz nem kulonul el a "flash" es a "ram" mint a szokasos esetekben - es emiatt kapom a targybeli hibauzenetet linkeleskor. Ez igy nyilvan rendben is van, de mivel ez tudatos, szeretnek megszabadulni ettol a figyelmeztetestol. Az interwebeken azt irjak hogy az .init meg a .text (READONLY) attributuma ezt megoldja, de sajna ez nem segit. Egyeb otlet? :) 

A rendszer egyebkent RISC-V + picolibc alapu, igy a hozza tartozo alap linker szkriptet (/usr/lib/picolibc/riscv64-unknown-elf/lib/picolibc.ld) modositottam egy kicsit hogy minden egy RAM blokkba keruljon. De egy kicsit el is vesztam az ilyen .text { ... } >ram AT>ram :text meg hasonlo nyalanksagokban is... 

Thx, A.