IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

8. diel - SDL - ERROR a logovanie

V dnešnom diele sa pozrieme na zachytávanie + errorov, ktoré SDL môže vyvolať a na ich následné logovanie. Rovnakým spôsobom môžeme samozrejme logovať aj akékoľvek ďalšie informácie.

ERROR

Pretože je SDL určené pre jazky C, nepracuje s výnimkami, ako to poznáme z C ++. To sa zmení, akonáhle použijeme objektový wrapper pre C ++. Do tej doby sa ale budeme musieť naučiť, ako pracovať s error v samotnom SDL.

Konvencie je relatívne jednoduchá. Pokiaľ sa jedná o funkciu, ktorá niečo vytvára (SDL_CreateRGBSurface, SDL_CreateWindow a iné), SDL vráti NULL. Všetky ostatné funkcie, vrátane napríklad SDL_Init, vracia 0 pri úspešnom vykonaní funkcie, v iných prípadoch vracia zápornú hodnotu. Je potreba po každej takejto operácii overiť, či funkcia prebehla v poriadku. Pokiaľ si nie sme istí, čo bude funkcia vracať, zistíme to v dokumentácii.

K samotnému získanie informácie o probléme, ktorý nastal, slúži funkcia SDL_GetError. Tá vracia const char *, teda reťazec obsahujúci bližšie určenie chyby. Tento text je vždy v angličtine. Po vyriešení ERROR by mala nasledovať funkcie SDL_ClearError, ktorá vyčistí vložený error. SDL_GetError po zavolaní tejto metódy (alebo keď nie je žiadny error) vráti prázdny reťazec. Nie je to však nutné, pretože pri ďalšom Error SDL premaže text pôvodného.

Posledný funkcia, ktorá sa u práce s error vyskytne, je SDL_SetError. Tá nastaví chybovú hlášku na reťazec, ktorý odovzdáme v parametri. Vzhľadom k tomu, že pracujeme v C ++, nebudeme túto funkciu využívať, pretože by tieto stavy mali byť vyriešené výnimkami. Ako som už spomenul, pridaním ďalšieho error sa predchádzajúce zmaže, to isté platí aj pre túto funkciu. Tiež pozor na návratovú hodnotu, tá je vždy -1.

Logy

Pri logovanie už je situácia o niečo pestrejšia. Logovanie pracuje s rôznymi prioritami a kategóriami. Najskôr si popíšeme jednotlivé kategórie a následne funkcie, ktoré SDL pre logovanie poskytuje. Logovanie sa tiež na každom OS chová odlišne. Na systémoch Windows sa bude logovať do debug výstupu (nie je ho teda možné použiť pre produkciu). Na systémoch Android bude výstup do klasického logovacieho výstupu. Na všetkých zostávajúcich systémoch sa budú logami zapisovať to štandardného error výstupu. Pre C ++ je to teda sderr. Tiež je potrebné dať pozor na dĺžku správy. Správa, ktorá má viac ako 4096 bajtov (4096 znakov), bude automaticky orezaná.

Kategórie

Jednotlivé kategórie logov sú vypísané v dokumentácii.

  • Aplication log je log týkajúce sa aplikácie. Môžeme u neho vypisovať logami oblasti štartu a vypnutie aplikácie, načítanie konfigurácie a podobné veci.
  • Error log je log týkajúce sa problémov v aplikácii. Spravidla sa sem zaraďujú správy, ktoré sme dostali z SDL_GetError.
  • Do systémového logu zapisujeme informácie, ktoré sa týkajú priamo systému. Môžeme tu napríklad zapísať informácie o hardvéri počítača a informácie pochádzajúce z operačného systému. Prečo sa nám tieto informácie hodí? Ak niekto bude našu aplikáciu používať na jeho stroji a niečo nebude fungovať, je vhodné mať aspoň nejaké informácie o stroji, na ktorom aplikácia beží.
  • Audio a Video logami slúži na informovanie o funkcii videá a audia. Môžeme tu napríklad vypísať, v akom rozlíšení bola vytvorená textúra alebo okno.
  • Ďalším logom je render log. Ten bude spravidla v blízkosti renderovací funkcie v nekonečnej slučke (pozri predchádzajúce kapitoly). Ideálne by mal byť tento log za každú funkcií, ktorá niečo vykresľuje (SDL_RenderCopy, SDL_RenderClear a iné).
  • Posledné prichystanú kategórií použiteľnú v aplikácii je input log, ktorý loguje informácie prúdiacej do aplikácie. Môžeme tu napríklad vypisovať, ktorú akciu užívateľ vykonal.
  • Okrem toho má SDL ďalšie dve kategórie, ktoré využijeme predovšetkým pri debugovania. Je to test a Assert log. Typickým príkladom sú testy aplikácie.

Poslednou kategóriou je custom log, ktorému môžeme priradiť čokoľvek. Spravidla si vytvárame vlastné kategórie, ktoré aplikácie potrebuje. Ak chceme tieto kategórie vytvoriť, napíšeme si vlastný Enumerátor, ale prvé hodnota musí byť rovnaká s SDL_LOG_CATEGORY_CUSTOM, aby nenastala kolízie s ostatnými kategóriami. Ako vytvoriť vlastnú kategóriu vidíme na nasledujúcom kóde.

enum
{
      MOJEAPLIKACE_CATEGORY_KATEGORIE1 = SDL_LOG_CATEGORY_CUSTOM,
      MOJEAPLIKACE _CATEGORY_KATEGORIE2,
      MOJEAPLIKACE _CATEGORY_KATEGORIE3,
      ...
};

Nie je nutne pravidlom, že musí byť použitá vždy presná kategórie. SDL pri logovanie jednotlivé kategórie nerozlišuje, je teda jedno, pod akou kategóriou informáciu zalogujeme. Kategória sa nám môžu hodiť neskôr, až si budeme vytvárať vlastné logovacie funkciu. Tá môže jednotlivé kategórie rozlišovať a správať sa pre nich rozdielne. Vlastné logovacie funkciu budem popisovať ďalej v článku.

Priority

Každý log tiež môže mať vlastné priority. Prioritou bližšie popíšeme, aká dôležitá je informácia, ktorú logu. Priority budem popisovať vzostupne podľa dôležitosti:

  • Verbose - v preklade niečo ako ukecaný. Pod touto prioritou si môžeme vypisovať ľubovoľné informácie. Môžeme vypisovať text, aby sme vedeli, na ktorom mieste programu sme. Väčšinu problémov riešených touto prioritou možno riešiť debuggerom.
  • Debug - pod touto prioritou budeme vypisovať informácie týkajúce sa debugovania. Môžeme vypisovať hodnoty premenných, ktoré nás zaujímajú, vypisovať aktuálny stav na určitom mieste programu a pod. Tieto problémy by sme mali opäť riešiť debuggerom.
  • Info - tu začínajú užitočnejšie priority, ktoré môžeme použiť v aplikácii. Pod info prioritou môžeme zverejňovať informácie, ktoré budú mať len informačný charakter. Napríklad "zapnutie aplikácie" alebo "načítanie konfigurácie". Ak budeme chcieť neskôr z logu zistiť, čo sa u používateľa stalo, pomôže nám info k približnému určenie oblasti, v ktorej k problému došlo.
  • Warn - priorita oznamujúce, že je pravdepodobne niečo v neporiadku. Pod touto prioritou budeme logovať informácie, ktoré sú mimo obvyklý chod aplikácie, ale nie sú dôležité do budúcnosti. Ak napríklad aplikácia bude chcieť načítať joystick, hoci ho nepoužíva (napríklad nie je v aktuálnom leveli potreba). Nie je to dôležitá súčasť systému, preto informáciu o tom, že sa nepodarilo načítať joystick, stačí označiť prioritou Warn.
  • Error - priorita oznamujúce problém v aplikácii. Ide o udalosť, ktorá priamo aplikáciu nevypne, ale spravidla je predzvesť konca. Napríklad keď sa nám nepodarí vytvoriť SDL_Surface, aplikácia spadne až vo chvíli, keď sa pokúsime tento SDL_Surface použiť. V kóde kontroly, či bol SDL_Surface vytvorený, môžeme zalogovať informáciu o probléme s prioritou error.
  • Critical - priorita spätá s kritickou situáciou v aplikácii. Ak sa vyskytne takáto udalosť, aplikácia spravidla nie je schopná pokračovať v práci. Takáto udalosť môže nastať napríklad keď sa nepodarí SDL inicializovať alebo vytvoriť okno. Po takýchto udalostiach nie je aplikácia schopná pokračovať a spadne alebo sa sama ukončí.

Logovanie

Najjednoduchšie funkcií pre logovanie je SDL_Log. Prijíma reťazec v rovnakom formáte, aký je u funkcia printf. V reťazci prijíma zástupné znaky ako "% i", "% f" a iné. Ďalšie parametre funkcie sú premenné, ktoré nahradia tieto zástupné znaky. Log sa touto funkciou zapíše do kategórie application s prioritou info.

Presným protikladom je funkcia SDL_LogMessage. Prvým parametrom je kategória, ktorú chceme logovať, druhým parametrom je potom priorita, pod ktorú budeme správu logovať. Tretím a štvrtým parametrom sú opäť reťazec a premenné, ktoré chceme zalogovať. Tieto parametre sú zhodné s parametrami SDL_Log.

Logovanie s určenou prioritou

Každá priorita má vlastné funkciu, ktorá loguje správy. Napríklad funkcia SDL_LogCritical zaloguje správu s prioritou critical. Kategóriu opäť určíme prvým parametrom, zvyšok parametrov je určený pre reťazec a premenné. Odporúčam používať tento súbor funkcií, nie ž samotnú funkciu SDL_LogMessage. Hoci je výsledok rovnaký, použitím určené funkcie bude kód prehľadnejšie a svojím spôsobom aj kratšie, pretože nemusíme vypisovať konštantu priority. Zoznam funkcií je tu.

Nastavenie zobrazených logov

Vyššie v článku som povedal, že SDL jednotlivé kategórie pri výstupe nerozlišuje. Na čo teda slúži? Pre každú kategóriu môžeme nastaviť prioritu, ktorá sa zobrazí na výstupe. Ak nastavíme napríklad ku kategórii aplication prioritu info, budú sa logovať všetky informácie s prioritou info, warning, error a critical. Na nastavenie priority pre kategóriu slúži funkcia SDL_LogSetPri­ority. Priority s vyššou dôležitosťou ako je priorita zadaná (vrátane) sa budú logovať, ostatné na výstupe neuvidíme. Môžeme tiež nastaviť rovnakú prioritu pre všetky kategórie, a to funkciou SDL_SetAllPri­ority.

V predvolenom nastavení má application kategórie nastavenú prioritu info, Assert kategórie prioritu warn a test kategórie prioritu verbose. Všetky ostatné kategórie majú nastavenú prioritu critical. Ak priority zmeníme a budeme ich chcieť vrátiť do východiskovej hodnoty, poslúži nám funkcia SDL_LogResetA­llPriorities.

Vlastný logovacie systém

SDL nám ponúka prostriedok, vďaka ktorému môžeme logovanie napojiť na vlastný logovacie systém, bez toho aby sme museli meniť už existujúcej aplikácie. Vystačíme si s jedinou funkciou, a to SDL_LogSetOutput­Function. Tá v prvom parametri prijíma callback, ktorý zavolá vždy, keď bude chcieť niečo zalogovať. V druhom parametra prijíma ukazovateľ na void, ktorý bude odovzdaný callbacku. Môžeme do neho vložiť triedu alebo štruktúru, ktorú budeme pri logovanie potrebovať. Musíme ale počítať s tým, že už túto triedu nemôžeme vymeniť za inú (bez znovu zavolanie funkcie). Callback nie je nič iné ako ukazovateľ na funkciu, ktorá vyzerá nasledovne.

void LogFunction(void* data, int kategorie, SDL_LogPriority priorita, const char* zprava);

Každá správa prejde cez túto funkciu, ktorá ju zaloguje (predvolený logovacie systém sa deaktivuje).

Ukážkový príklad

ukážka logovanie - SDĽ
Ako ukážku si vezmeme príklad z minulej lekcie a doplníme do neho logovanie (každý sa môžete skúsiť zamyslieť, ako by to vyzeralo - moje riešenie si môžete stiahnuť pod článkom). Overíme každú funkciu, ktorú overiť môžeme a pokiaľ nastane problém, zalogujeme ho. Rovnakým spôsobom by mala byť postavená každá aplikácia. Aby sme videli, ako SDL loguje správy s rozdielnou kategórií a prioritou, vložím do programu pár logov, ktoré sa zalogují vždy.

Všimnime si predovšetkým inicializačnej funkcie. Vidíme, že pre každú časť knižnice (SDL, TTF, IMG) sa kód líšia. Pre SDL vráti funkcie pri neúspechu zápornú hodnotu. IMG naopak pri úspechu vracia konštantu, ktorú sme odovzdali v parametri, a pri neúspechu 0. Je vždy nutné overiť v dokumentácii, ako funkcia reaguje na zlé parametre alebo prostredia.

To je pre dnešné lekciu všetko. V budúcom dieli sa pozrieme na časovač a na optimalizáciu FPS, teda snímok za sekundu tak, aby bola aplikácia čo najplynulejší a zároveň spotrebovala čo najmenej procesorového času.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 829x (9.58 MB)

 

Predchádzajúci článok
SDĽ - Práca s 16 a 32-bitovou grafikou
Všetky články v sekcii
SDĽ
Preskočiť článok
(neodporúčame)
SDĽ - Práca s časovačom
Článok pre vás napísal Patrik Valkovič
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Věnuji se programování v C++ a C#. Kromě toho také programuji v PHP (Nette) a JavaScriptu (NodeJS).
Aktivity