Documentation
¶
Overview ¶
Package structlayout holds the pure, pipeline-agnostic helpers for deciding whether a C struct can be surfaced as a plain Go value struct that reproduces the C ABI, and for width-correcting struct field Go types.
These functions operate only on strings, []string, and ints — they have no dependency on the frameworks (purego) or libraries (cgo) metadata models or type mappers — so both pipelines can share them. Struct emission itself stays pipeline-specific; only the ABI/layout reasoning lives here.
SCOPE — shared: used by both the frameworks (purego) and libraries (cgo) pipelines. Keep it dependency-free of either pipeline's mapper/metadata.
Index ¶
- Variables
- func AlignElem(align int, packed bool) string
- func GoStructLayout(goTypes []string, packed bool, sizer FieldSizer) (offsets []int, size int, ok bool)
- func IsPrimitiveOrArrayOf(goType string, ok func(elem string) bool) bool
- func LayoutMatchesAuthoritative(size int, packed bool, fieldOffsets []int, goTypes []string, sizer FieldSizer) bool
- func LayoutSafeFromGoTypes(packed bool, goTypes []string) bool
- func ScalarGoSizeAlign(goType string) (size, align int, ok bool)
- func StructFieldGoType(objcType, mapped string) string
- type FieldSizer
Constants ¶
This section is empty.
Variables ¶
var Primitives = map[string]bool{ "bool": true, "byte": true, "rune": true, "uintptr": true, "int": true, "int8": true, "int16": true, "int32": true, "int64": true, "uint": true, "uint8": true, "uint16": true, "uint32": true, "uint64": true, "float32": true, "float64": true, }
Primitives is the set of Go primitive types a value-struct field may use directly. A field of any other bare type must be another emittable struct in the same package (checked via the emittable fixpoint in the caller).
Functions ¶
func AlignElem ¶
AlignElem returns the Go type of a leading `_ [0]<elem>` field that forces a byte-array backing struct's alignment to the C alignment, or "" when none is needed. A packed struct is C-aligned to 1 (a plain [N]byte already matches). Go has no scalar wider than 8-byte alignment, so a 16-byte-aligned C type (rare SIMD) is aligned to 8 — the authoritative size is always a multiple of the C alignment, so a Go struct rounded up to <=8 never changes the size. Both the frameworks idiomatic and raw emitters share this.
func GoStructLayout ¶
func GoStructLayout(goTypes []string, packed bool, sizer FieldSizer) (offsets []int, size int, ok bool)
GoStructLayout computes each field's byte offset and the total size of a Go struct with the given (width-corrected) field types, under Go's natural alignment (packed=false) or tight packing (packed=true). ok is false if any field's size is unknown.
func IsPrimitiveOrArrayOf ¶
IsPrimitiveOrArrayOf reports whether goType is a bare identifier (or a fixed-size array, possibly multi-dimensional, of one) whose element satisfies ok. A slice "[]T", a pointer, or a qualified/expression type is rejected.
func LayoutMatchesAuthoritative ¶
func LayoutMatchesAuthoritative(size int, packed bool, fieldOffsets []int, goTypes []string, sizer FieldSizer) bool
LayoutMatchesAuthoritative verifies the width-corrected Go layout reproduces clang's authoritative record layout (per-field offsets + total size) when one was captured (size != 0). It returns true when no authoritative layout exists (nothing to cross-check — clang only lays out value-used structs) or when the Go layout matches exactly. A mismatch means the Go struct would not reproduce the C ABI, so the caller should keep the struct opaque.
fieldOffsets holds the authoritative byte offset of each field (in field order); its length is the struct's field count.
func LayoutSafeFromGoTypes ¶
LayoutSafeFromGoTypes reports whether a plain Go struct reproduces the C ABI field offsets of a struct — the condition under which reading fields through a pointer to the C data is correct. An unpacked struct always qualifies (Go and C use the same natural alignment for these scalar fields). A packed struct qualifies when every field is already naturally aligned at its packed offset, so Go inserts no inter-field padding. Trailing padding is deliberately NOT required: a packed struct ending on an odd size (e.g. IOUSBConfiguration Descriptor's 9 bytes) makes the Go value one byte larger, which is immaterial for pointer field access (the only way these are surfaced) though it means the value should not be bulk-copied out of a tightly-sized C allocation. A field whose Go type is not a fixed-width scalar makes the result false (conservative: the opaque path handles it).
func ScalarGoSizeAlign ¶
ScalarGoSizeAlign returns the size and alignment (in bytes, arm64/amd64 LP64) of a hermetic scalar Go type, and ok=false for anything else (a nested struct, pointer, slice, or unresolved type). Only fixed-width types are admitted; notably Go int/uint/uintptr are 8 bytes here, so a field the mapper resolved to a platform-width int is treated as 8 — matching the LP64 C `long`/pointer it came from.
func StructFieldGoType ¶
StructFieldGoType corrects a struct field's Go type to the exact C ABI width where the type mapper widened a native C int to Go int/uint (8 bytes) even though a C int is 4. Struct fields — unlike function parameters — must match the C width exactly, or the Go struct would mislay every field after the first int. Arrays are corrected element-wise (int[4] → [4]int32). Other types (short→int16, long→int, stdint) already match and pass through.
Types ¶
type FieldSizer ¶
FieldSizer resolves the size and alignment (bytes) of a non-primitive field Go type — an enum (by its underlying integer width) or a nested value struct (by its own layout) — and ok=false when goType is neither. It lets the layout helpers validate structs whose fields are not plain scalars. May be nil.