Zjištění verze knihovny GLib
Verze knihovny GLib je zaznamenaná ve trojici maker:
#define GLIB_MAJOR_VERSION
#define GLIB_MINOR_VERSION
#define GLIB_MICRO_VERSION
Každé makro znamená jednu složku čísla verze knihovny:
GLib version 1. 2. 8
| | |
| | V
| V GLIB_MICRO_VERSION
V GLIB_MINOR_VERSION
GLIB_MAJOR_VERSION
Ve svých programech je můžete využít třeba k výpisu informace o verzi, pod kterou byla aplikace zkompilována.
Chcete-li naopak zkontrolovat, je-li program sestavován pod vámi požadovanou verzí knihovny, můžete s úspěchem využít následující makro:
#define GLIB_CHECK_VERSION(major,minor,micro)
Makro vrátí TRUE, je-li aktuální verze knihovny stejná nebo lepší než zadaná verze major. minor. micro.
Oddělovače
Nepříjemnost s různými oddělovači adresářů na různých platformách řeší následující konstantní makra:
#define G_DIR_SEPARATOR
#define G_DIR_SEPARATOR_S
G_DIR_SEPARATOR je na Unixech roven '/' a ve Windows '\'. V makru G_DIR_SEPARATOR_S je definováno totéž, ale jako řetězec (tedy "/" a "\").
Podobně se věci mají i u těchto maker:
#define G_SEARCHPATH_SEPARATOR
#define G_SEARCHPATH_SEPARATOR_S
G_SEARCHPATH_SEPARATOR uchovává oddělovač cest v proměnné prostředí PATH. V Unixu je to dvojtečka ( ':') a ve Windows středník ( ';'). Potřebujete-li oddělovač cest zapsaný jako řetězec, sáhněte po G_SEARCHPATH_SEPARATOR_S.
Boolovské hodnoty
V dřívějších dílech jsem běžně v příkladech používal boolovské konstanty TRUE a FALSE (což není standardní výbava jazyka C), aniž bych se předtím zmínil o tom, že jsou definovány v knihovně GLib. Za to se všem omlouvám a jen pro pořádek uvádím jejich definici:
#define FALSE (0)
#define TRUE (!FALSE)
Stejně tak makro
#define NULL ((void*) 0)
…označující prázdný ( NULL ový) pointer.
Větší, menší
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
…jednoduchá makra, jejichž výsledkem je menší (větší) číslo z a a b.
Výpočet absolutní hodnoty je realizován makrem:
#define ABS(a) (((a) < 0) ? -(a) : (a))
Pro zarovnání hodnoty do číselného intervalu slouží makro:
#define CLAMP(x, low, high) \
(((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
Jeho výsledkem je zadané číslo x, pokud se nachází v rozmezí hodnot low a high. Je-li x menší, vrátí se low, je-li větší, předá se high.
Například výsledkem všech tří následujících volání bude číslo 10:
CLAMP(5, 10, 15) CLAMP(10, 5, 20) CLAMP(25, 5, 10)
Struktury na úrovni bajtů
#define G_STRUCT_OFFSET(struct_type, member)
…vrátí offset v bajtech položky member struktury struct_type. Argument struct_type je tedy název datového typu struktury (např. GString) a member název položky, jejíž adresový offset chceme získat (např. len).
#define G_STRUCT_MEMBER(member_type, struct_p, struct_offset)
…zpřístupní v konkrétní instanci struktury, na níž ukazuje pointer struct_p, položku s offsetem struct_offset a výsledek přetypuje na typ member_type.
#define G_STRUCT_MEMBER_P(struct_p, struct_offset)
…vrátí beztypový Pointer na položku s offsetem struct_offset struktury struct_p.
Příklad:
#include <glib.h>
typedef struct {
char *nazev;
float max_rychlost;
float spotreba;
} Automobil;
int main(void) {
Automobil auto1 = { "Skoda", 130, 7.2 };
Automobil auto2 = { "Audi", 220, 10.4 };
gulong o_nazev = G_STRUCT_OFFSET(Automobil, nazev);
gulong o_spotreba = G_STRUCT_OFFSET(Automobil, spotreba);
printf("%s ma spotrebu %0.1f litru\n",
G_STRUCT_MEMBER(char*, &auto1, o_nazev),
G_STRUCT_MEMBER(float, &auto1, o_spotreba));
printf("%s ma spotrebu %0.1f litru\n",
G_STRUCT_MEMBER(char*, &auto2, o_nazev),
G_STRUCT_MEMBER(float, &auto2, o_spotreba));
return 0;
}
Tato ukázka vypíše na terminál:
Skoda ma spotrebu 7.2 litru Audi ma spotrebu 10.4 litru
Cesty a jména
gchar* g_get_prgname(void);
…vrátí jméno programového souboru. Pokud používáte knihovnu GDK nebo GTK, je jméno programu inicializováno automaticky ve funkci gdk_init(), která je volána z funkce gtk_init(). Název se zjistí z poslední složky řetězce argv[0]. Jestliže ale výše zmiňované knihovny nepoužíváte a přesto máte pro funkci g_get_prgname() uplatnění, musíte název programu inicializovat sami:
void g_set_prgname(const gchar *prgname);
Na původu řetězce prgname nezáleží, protože rutina si pro název programu alokuje nový řetězec.
Pro získání hodnoty proměnné prostředí poskytuje GLib přenositelnou funkci
gchar* g_getenv(const gchar *variable);
Argument variable je název proměnné prostředí a navrácený řetězec je její hodnota, nebo NULL, pokud taková proměnná není definována. Pozn.: ve Windows je vrácený řetězec platný jen do dalšího volání g_getenv().
Funkce
gchar* g_get_user_name(void);
…vrátí jméno (login) aktuálního uživatele. Pokud na dané platformě není možné jméno zjistit, funkce vrátí řetězec "somebody".
Podobně tak funkce
gchar* g_get_real_name(void);
…vracející skutečné jméno uživatele (viz. /etc/passwd). Pokud nelze zjistit, vrátí se "Unknown".
Domácí adresář uživatele, adresář pro dočasné soubory (tmp, temp) a aktuální adresář zjistíte pomocí funkcí:
gchar* g_get_home_dir(void); gchar* g_get_tmp_dir(void); gchar* g_get_current_dir(void);
Funkce hledají zmíněné informace v proměnných prostředí HOME (ve Windows NT i HOMEDRIVE a HOMEPATH), TMPDIR, TMP, TEMP…
Další práce s cestami k souborům
gchar* g_basename(const gchar *file_name);
…vrátí jméno souboru bez předcházející adresářové složky. Vrácený řetězcový pointer ukazuje přímo doprostřed argumentu file_name.
gchar* g_dirname(const gchar *file_name);
…vrátí adresářovou složku jména souboru file_name. Pokud file_name neobsahuje cestu i s adresáři, použije se jako návratová hodnota řetězec ".". Vrácená hodnota by měla být po použití dealokována.
gboolean g_path_is_absolute(const gchar *file_name);
…vrátí TRUE, jestliže je jméno souboru file_name absolutní, tj. rozhodne, jestli obsahuje plnou cestu z kořenového adresáře. (Např. „ /usr/local“ v Unixech nebo „ C:\WINDOWS\SYSTEM“ ve Windows.)
gchar* g_path_skip_root(gchar *file_name);
…vrátí pointer na jméno souboru file_name těsně za označením kořenového adresáře, tj. za lomítkem ( /) v Unixech a za C:\ ve Windows. Jestliže file_name není absolutní jméno souboru, funkce předá NULL.
Pokračování příště.