You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sometimes you don't want to call a C function; you just want to use C's knowledge of memory layout. If you are parsing a binary file format or a network protocol defined in a C header, you could manually calculate offsets and padding, but that is a recipe for "off-by-one" disasters.
Affix allows you to use its internal JIT compiler to perform runtime introspection on types, giving you the exact sizeof and offsetof values for the current CPU architecture.
The Recipe
We will define a complex, padded C struct and use Affix to write a "pure Perl" binary parser that respects C's alignment rules.
use v5.40;
use Affix qw[:all];
# 1. Define the structure in the global registry
typedef Header=> Struct [
magic=> Array [ Char, 4 ],
version=> UInt16,
_pad=> UInt16, # Manual padding is often needed in binary formatsflags=> UInt32,
offset=> UInt64
];
# 2. Introspect the layoutmy$size = sizeof Header();
my$v_off = offsetof Header(), 'version';
my$f_off = offsetof Header(), 'flags';
say"Total Struct Size: $size bytes";
say'Version field starts at byte: ' . $v_off;
say'Flags field starts at byte: ' . $f_off;
# 3. Use this info to parse raw data (e.g. from a file)# Build a 24-byte buffer that matches the aligned layout.# Note: the UInt64 'offset' field is aligned to an 8-byte boundary, so it# actually starts at byte 16 (not byte 12) even though the preceding fields# only take up 12 bytes.my$raw_data = pack'a4vvVx4Q', 'AFFX', 1, 0, 0xFF, 0x1234;
# Copy the raw bytes into a heap buffer, then plate the struct over itmy$buf = calloc 1, sizeof Header();
memcpy $buf, $raw_data, length$raw_data;
my$header = cast $buf, Header();
if ( $header->{magic} eq'AFFX' ) {
say'Valid header found!';
saysprintf'Flags: 0x%X', $header->{flags};
saysprintf'Offset: 0x%X', $header->{offset};
}
The output looks like this:
Total Struct Size: 24 bytes
Version field starts at byte: 4
Flags field starts at byte: 8
Valid header found!
Flags: 0xFF
Offset: 0x1234
How It Works
Compiler-Grade Accuracy
When you call sizeof or offsetof, Affix isn't guessing. It uses the infix engine to perform a full mock-layout of the structure according to the System V or Windows ABI. It accounts for tail-padding and member alignment automatically.
Zero-Header Parsing
Affix can't "plate" a struct directly over a Perl string buffer (the string is not addressable, writable C memory). Instead, you calloc a heap buffer the size of your struct, memcpy your raw bytes into it, and then cast that buffer to the struct type. Accessing $header->{flags} performs a raw memory read at the exact offset calculated during introspection — and since the view is zero-copy, writes through $header go straight back into the buffer.
Kitchen Reminders
Packing Rules
Standard C structs often have "hidden" padding. For example, a char followed by an int will usually have 3 bytes of invisible padding between them so the int starts on a 4-byte boundary. offsetof is the only safe way to find where that int actually lives.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Sometimes you don't want to call a C function; you just want to use C's knowledge of memory layout. If you are parsing a binary file format or a network protocol defined in a C header, you could manually calculate offsets and padding, but that is a recipe for "off-by-one" disasters.
Affix allows you to use its internal JIT compiler to perform runtime introspection on types, giving you the exact
sizeofandoffsetofvalues for the current CPU architecture.The Recipe
We will define a complex, padded C struct and use Affix to write a "pure Perl" binary parser that respects C's alignment rules.
The output looks like this:
How It Works
When you call
sizeoforoffsetof, Affix isn't guessing. It uses theinfixengine to perform a full mock-layout of the structure according to the System V or Windows ABI. It accounts for tail-padding and member alignment automatically.Affix can't "plate" a struct directly over a Perl string buffer (the string is not addressable, writable C memory). Instead, you
calloca heap buffer the size of your struct,memcpyyour raw bytes into it, and thencastthat buffer to the struct type. Accessing$header->{flags}performs a raw memory read at the exact offset calculated during introspection — and since the view is zero-copy, writes through$headergo straight back into the buffer.Kitchen Reminders
Standard C structs often have "hidden" padding. For example, a
charfollowed by anintwill usually have 3 bytes of invisible padding between them so theintstarts on a 4-byte boundary.offsetofis the only safe way to find where thatintactually lives.All reactions