libxkbcommon 1.14.0-beta1
Library implementing the XKB specification for parsing keyboard descriptions and handling keyboard state
Loading...
Searching...
No Matches
Data Structures
Extensible structure ABI contract
Collaboration diagram for Extensible structure ABI contract:

Data Structures

struct  xkb_keymap_serialize_config
 
struct  xkb_keymap_serialize_result
 
struct  xkb_state_components_update
 
struct  xkb_layout_policy_update
 
struct  xkb_state_update
 

Detailed Description

Explains how extensible structures maintain ABI compatibility across library releases.

To guarantee long-term forward and backward compatibility of the ABI, functions across this library accept extensible structures that share a common ABI contract.

Layout

Every extensible structure begins with a mandatory uint32_t size first field and must not contain any implicit padding: every alignment gap is filled explicitly with a reserved field, each sized for the platform with the strictest alignment requirements and verified via static_assert.

struct Example {
uint32_t size;
uint8_t a;
uint8_t reserved0[3];
char *b;
uint32_t c;
uint32_t reserved1; // padding for 64-bit platforms
};

size specifies the byte size of the structure, as provided by the caller. It has a fixed-width type uint32_t so that its representation is independent of the platform’s native size_t width.

A structure’s reserved fields (reserved0, reserved1, …) either fill an alignment gap or pre-allocate space for a future field. They are numbered in declaration order; when one is later repurposed (see Compatibility guarantees), remaining reserved fields keep their names.

Structure initialization

When initializing an extensible structure, callers must:

struct Example example = {
.size = sizeof(example),
.a = …,
// .reserved0 is zeroed automatically
.b = …,
.c = …,
// .reserved1 is zeroed automatically
};

Version resolution

When a function receives an extensible structure, it uses the caller- provided size to determine which fields are present, and validates any reserved field covered by that size:

Backward compatibility

The caller was built against an older header: caller’s size < library’s. Only the fields covered by size are read; the library never accesses memory past that boundary. Fields beyond it are treated as unset and fall back to their default behavior.

In the unlikely case that a missing field has no safe default for the requested operation, the call fails with XKB_ERROR_ABI_BACKWARD_COMPAT.

Forward compatibility
The caller was built against a header identical to or newer than the library: *caller’s size \≥ library’s* (note that equal size does not imply same version: Reserved fields below). Only the fields known to this version of the library are read. The trailing, unrecognized bytes (if any) are inspected only to check they are zero. If they are all zero, they are silently ignored: the caller is requesting default behavior for fields this library predates. If any are non-zero, the caller is explicitly requesting behavior this library version cannot provide, and the call fails with XKB_ERROR_ABI_FORWARD_COMPAT.
Reserved fields
Independently of the above, every reserved field covered by size must be zero. A non-zero value means the caller was built against a header where that field has since been given meaning — behavior this library version cannot honor — and the call fails with XKB_ERROR_ABI_FORWARD_COMPAT, the same code used for non-zero trailing bytes beyond size.
Invalid
If size is smaller than the very first released version of the struct (e.g. left uninitialized) or excessively big (e.g. corrupted), the call fails safely with XKB_ERROR_ABI_INVALID_STRUCT_SIZE.

Compatibility guarantees

This contract holds as long as fields are only ever appended to an extensible structure: never removed, reordered, or resized. A reserved field may later be repurposed by renaming it and giving it a new ABI-compatible type, so that the structure’s layout is unchanged. Under these rules:

Since
1.14.0