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

Fórumok

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ások

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.