Különböző struct átadása függvénynek

 ( igiboy | 2019. február 17., vasárnap - 20:22 )

Pár napja próbálok rájönni az optimális megoldásra, lehet alapjában rossz felé keresek, így az alap problémámat is leírom és azt is, hogy én mire gondoltam mint megoldás. Viszont annak a megvalósításánál gondba ütközök.

EEPROM-ba szeretnék menteni konfigurációs adatot, paramétereket, válozókat. Célszerű ezt laponként kezelni és egyben kiírni akár. Ha változónként teszem akkor is hasonló lenne a helyzet.
A lap mérete 64 byte.
Az egyes lapokat struct-ba próbálnám rendezni, így a program futási ideje alatt a változók elérhetőek lennének. Emellett tudnám tárolni a lap kezdőcímét.
Kb. valahogy így:
typedef struct {
unsigned char page;
char ssid[32];
char psk[32];
} eewifi;

typedef struct {
unsigned char page;
char temp1;
char temp2[2];
long temp3;
} eetemp;

eewifi page_wifi1;
eewifi page_wifi2;
eetemp page_temp;

Nem egyforma méretűek, a szervezési viszont mindegyiknek azonos, az elején van egy cím, utána az adatok (max 64byte).
Szeretném 1 függvénnyel kezelni az eewifi, eetemp típusokat.
Pl. írni egy olyan függvényt ami kiírja a benne tárolt összes adatot, tehát eewifi-nél a címét és 64 byte-ot az eetemp-nél pedig a címét és 7 byte-ot.

A végső cél, hogy az egyes lapokat amiket struct-ba szerveztem kiolvasó és beíró függvénnyel kezeljem. A későbbiekben ne kelljen mindegyik struct-ra egyedit írni.

Próbáltam a pointerek világában elmerülni, de eddig vagy már fordítási hibába került, vagy pedig nem azt adta vissza amit vártam volna.

Ilyen dolgokat mikrovezérlőn ASM-ben megírtam amit akartam, persze vigyázva arra, hogy ne írjak felül semmit, onnan olvassak ahonnan kell, stb... Most viszont x86-on próbálnám előbb, hogy működik-e az elgondolás majd később ESP32-re menne a program.

Szívesen veszek bármilyen iránymutatást, vagy akár egy működő programrészt ami kiírja bármelyik struct tartalmát, ahogy fentebb vázoltam.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Erre a problemakorre egy sizeof segitsegevel feljavitott #define-os makro lehet a kulcs.

A masik megoldasi irany lehet az union alkalmazasa.

De mindenekelott azt nem latom pontosan h ez a 8-bites page mi a fityfenere is kell pontosan. A cim mar 8bitbe nem fer bele, es ha le is tarolod a cimet valahova akkor csak abbol nem fogod megtalalni - ha meg tudod a cimet akkor minek irod be(le)? Szoval ez itten zavaros...

A cím az nem a teljes címe az adatnak. Inkább olyasmit jelent, hogy hányadik lap. Azt majd a beíró rész lekezeli. Megszorozza annyival amennyivel kell.

Union-os megoldással is próbálkoztam, a problémám ugyanaz volt. Az uniont átadom, viszont belül már lehetnek különbözőek a struct-ok itt véreztem el.

Egy favágó megoldás...
(és nem próbáltam ki ;)

Egyébként direkt 31 byte az ssid és a psk max mérete? (standard string műveletek esetén)


#define EEWIFI_PAYLOAD_LEN (sizeof(eewifi)-1)
#define EETEMP_PAYLOAD_LEN (sizeof(eetemp)-1)

static int eeprom_write(void* data, int len)
{
  unsigned char page = *(unsigned char*)data;
  return akarmi(page, data+1, len); // +1 = skip page index byte
}


main()
{
  eewifi page_wifi2;
  eetemp page_temp;
  
  ...

  eeprom_write(page_wifi2, EEWIFI_PAYLOAD_LEN);
  eeprom_write(page_temp, EETEMP_PAYLOAD_LEN);
}

Úgy néz ki megvan egyelőre az irány.
Így kiolvasható bármely struct-ban tárol adat.
Elsőre ott követtem el a hibát, hogy az átadott struct méretét a függvényen belül akartam kitalálni. Valahogy ellenkezett a logikámmal hogy pár karakterrel később adjam meg újra ugyanazt a változó nevét amit át akarok adni.
#define-al akár megoldhatom hogy csak 1 alkalommal kelljen a függvénynek megadni az adott struct nevét, így az esetleges copy-paste hiba kikerülhető.

Közben teszteltem. Eddig úgy néz ki a problémám megoldódott.
Köszi!

//SSID,PSK mérete így alakult. Úgy voltam vele, hogy ne 8 karakter legyen a korlát. Volt egy klímás topic itt amiben az lett a csatlakozási probléma megoldása, hogy a hosszú SSID vagy PSK-t nem kezelte le az IoT modul a klímán.

Én olyan megoldással is találkoztam, szintén konfiguráció, ahol a struktúrát egy makróval hozták létre, és volt egy fejléce, ami általános volt, tartalmazta a struktúra elemszámát, és "típusát" (milyen komponens használja).
Az elemek is általában struktúrák, de változó számú lehet, viszont azokat már a feldolgozó komponens ismeri, egy kis pointerezés után jól kezelhető.

Software is like sex, it's better with a penguin. :D (r)(tm)(c) آكوش

Ha c++17 vagy boost megengedett: std::variant/boost::variant -> https://en.cppreference.com/w/cpp/utility/variant
Maskulonben: tagged union -> http://www.drdobbs.com/tagged-unions/184401905

A kodbol ugy tunik, hogy itt c-ben tortennek a dolgok, szoval szerintem a tagged union lesz a te embered.

Nem ismerem a kornyezetet, de valami olyasmi a lenyeg, hogy az unio egyik tagja egy sima char[64] lesz, es a fuggveny, ami az irasert/olvasasert felel, az ezt irja ki/olvassa be. (gy.k.: mindig kitolja/beolvassa a teljes lapot). Ez a konkret helyzettol fuggoen lehet helyes es helytelen. Ha valamiert nem jarhato, akkor a tag alapjan kell irni egy switch-et (c++ terminologiaval visitort :) ), ami elvegzi a piszkos munkat, igy egy kicsit melosabb ugyanakkor pedansabb a dolog (mivelhogy csak azokat a byte-okat irja olvassa, amik erdemi adatot tartalmaznak, nem pedig egy komplett lapot). De akarhogy is, lesz egy fuggvenyed, ami kapni fog egy ilyen tagged union strukturat, es majd o szepen megoldja a dolgokat.

Ha jól értem különféle struktúrákat akarsz egy eljárással kezelni?
Kicsit furcsa és nem túl biztonságos. Ha nagyon kellene akkor először is a struktúrákat ellátnám valamilyen azonosítóval, majd ronggyá kasztolnám.

* Én egy indián vagyok. Minden indián hazudik.