Modul struct
se dá použít především asi ve dvou situacích:
Co se céčkovských struktur týká, hlídejte si zarovnání bajtů – výchozí nastavení replikuje obsazení paměti přesně podle Céčka, což ne vždy můžete potřebovat.
Abychom věděli, o čem budeme mluvit, ukažme si nejdříve jednoduchý příklad: Nechť je délka dat „chunku“ v PNG-souboru určena čtveřicí bajtů b'\x00\x00\x01\x4d'
. Kolik bajtů tato data zabírají?
Pro vyřešení musíme vědět, že čísla jsou v PNG zapsána v pořadí big-endian a jde o klasický čtyřbajtový int:
Znak >
v tzv. formátovacím řetězci říká, že jde o pořadí big-endian, a znak I
pak udává, že jde o čtyřbajtové celé číslo. Hledaná délka je tedy 333 bajtů.
Formátovací řetězec určuje, jakým způsobem bude sekvence bajtů na vstupu převedena na požadované výstupní hodnoty a naopak. Skládá se ze dvou částí:
Vstupních hodnot (ať už k převodu na bajty nebo naopak bajtů k převodu na hodnoty) přitom může být libovolný počet a rozbalení je možné provést i iteračně (metodou iter_unpack()).
Pro nastavení těchto tří základních vlastností překladu je k dispozici následujících pět znaků (přitom jeden z nich je alias):
znak | pořadí bajtů | velikost | zarovnání |
---|---|---|---|
@ |
přirozené | přirozená | přirozené |
= |
přirozené | standardní | žádné |
< |
little-endian | standardní | žádné |
> |
big-endian | standardní | žádné |
! |
síťové (big-endian) | standardní | žádné |
Nevyplníte-li tento znak, je automaticky předpokládán @
, což znamená, že si váš kód bude rozumět s céčkovskými struturami vyrobenými stejným překladačem na stejné platformě. Pro jiná použití ho proto nezapomeňte nastavit na požadovanou hodnotu!
Ty z příkladů dále, které užívají přirozené nastavení, byly spouštěny na 64-bitovém little-endian systému:
Pro rychlé připomenutí zde okopíruji podstatnou část tabulky z oficiální dokumentace:
příznak | typ v Céčku | typ v Python'u | standardní velikost |
---|---|---|---|
x |
zarovnávací bajt | ||
c |
char | byte o délce 1 | 1 |
b |
signed char | int | 1 |
B |
unsigned char | int | 1 |
? |
_Bool | bool | 1 |
h |
short | int | 2 |
H |
unsigned short | int | 2 |
i |
int | int | 4 |
I |
unsigned int | int | 4 |
l |
long | int | 4 |
L |
unsigned long | int | 4 |
q |
long long | int | 8 |
Q |
unsigned long long | int | 8 |
n |
ssize_t | int | |
N |
size_t | int | |
f |
float | float | 4 |
d |
double | float | 8 |
s |
char[] | byte | |
p |
char[] | byte | |
P |
void * | int |
Nicméně mějte na paměti, že v originále se k tabulce váže hromada poznámek, které mohou být v konkrétních případech velmi důležité!
Vícenásobné opakování stejného příznaku můžete také zapsat pomocí čísla před ním, například:
Přitom mezi číslem a příznakem nesmí být mezery (zatímco mezi jednotlivými příznaky ano).
Pro příznaky s a c má opakování maličko jiný význam – zatímco 10s je desetibajtový řetězec, 10c je prostě deset znaků. A varianty s nulou pak představují jeden konkrétní prázdný řetězec, respektive právě nula znaků.
Používáte-li nějaký konkrétní formátovací řetězec vícekrát, je vhodné pro něj zavést vlastní objekt..
..na kterém jsou dostupné prakticky všechny metody modulu struct (výjimkou je metoda calcsize(), kterou nahrazuje atribut size se stejným významem). Ušetříte tím totiž na neustálé kompilaci formátovacího řetězce.
Balení (a rozbalování) pro přesně určenou endianitu je snad celkem průhledné:
U přirozeného nastavení už to ale stojí chvilku počítání bitů, než se člověk zorientuje:
Zatímco pořadí 'cl'
je zarovnáno na 2*8 bitů, u pořadí 'lc'
už to není pravda. Vhodné zarovnání se ale dá vnutit pomocí speciální konstrukce 0Příznak
na konci, kde volba příznaku zařídí dorovnání příslušným počtem bajtových nul:
Nejen vzhledem k chování přirozeného zarovnání se vyplatí vědět, kolik bajtů vlastně uvedená struktura zabere. K tomu slouží metoda calcsize('FORMAT'):
Pro předkompilované formátovací objekty pak máme k dispozici následující jejich atributy:
Sekvenci stejně zabalených (n-tic) hodnot můžeme rozbalit také iterativně:
'>hhh'
bychom iterovali jako '>h'
).
Kromě předchozích metod modul struct podporuje také zápis/čtení do/z binárních bafrů:
Jedná se o standardní výjimku modulu struct, kterou vrací jeho metody, dojde-li při jejich provádění k chybě.