Skill Index

atopile/

pyzig

community[skill]

How the Zig↔Python binding layer works (pyzig), including build-on-import, wrapper generation patterns, ownership rules, and where to add new exported APIs. Use when adding Zig-Python bindings, modifying native extensions, or debugging C-API interactions.

$/plugin install atopile

details

Pyzig Module

pyzig is the Zig↔Python interoperability layer used by Faebryk’s native modules (graph, sexp, faebryk typegraph, …).

There are three distinct layers to keep straight:

  • Python loader/glue: src/faebryk/core/zig/__init__.py (build-on-import + .pyi syncing)
  • Zig build: src/faebryk/core/zig/build.zig (builds pyzig.so + pyzig_sexp.so, generates stubs)
  • Zig binding utilities: src/faebryk/core/zig/src/pyzig/* (wrapper generation + minimal C-API surface)

Quick Start

ato dev compile
python -c "import faebryk.core.zig; import faebryk.core.graph"

Relevant Files

  • Python-side loader/build glue:
    • src/faebryk/core/zig/__init__.py (ZIG_NORECOMPILE, ZIG_RELEASEMODE, lock, stub syncing)
  • Zig build + stub generation:
    • src/faebryk/core/zig/build.zig (builds extensions + runs .pyi generator)
  • Core pyzig utilities:
    • src/faebryk/core/zig/src/pyzig/pybindings.zig (minimal CPython C-API declarations)
    • src/faebryk/core/zig/src/pyzig/pyzig.zig (wrapper generation helpers)
    • src/faebryk/core/zig/src/pyzig/type_registry.zig (global type-object registry)
    • src/faebryk/core/zig/src/pyzig/pyi.zig (stub generation helpers)
  • Example consumers:
    • src/faebryk/core/zig/src/python/graph/graph_py.zig
    • src/faebryk/core/zig/src/python/sexp/sexp_py.zig

Dependants (Call Sites)

  • Graph bindings: src/faebryk/core/zig/src/python/graph/*
  • Sexp bindings: src/faebryk/core/zig/src/python/sexp/*
  • TypeGraph bindings: src/faebryk/core/zig/src/python/faebryk/* (and friends)

How to Work With / Develop / Test

Core Concepts

  • Direct binding: pyzig calls the CPython C-API directly (no cffi/ctypes).
  • Wrapper types: most exposed Zig structs become Python heap types via wrap_in_python(...) / wrap_in_python_simple(...).
  • Global type registry: prevents re-creating Python PyTypeObjects for the same Zig type (type_registry).
  • No direct __init__ (by default): many “reference” types are not meant to be user-constructed; pyzig often installs an init that raises.
  • Debug handle: generated wrappers include __zig_address__() to help debug pointer identity.

Development Workflow

  1. Edit Zig:
    • binding helpers: src/faebryk/core/zig/src/pyzig/*
    • module wrappers: src/faebryk/core/zig/src/python/**
  2. Rebuild native modules:
    • ato dev compile (imports faebryk.core.zig; editable installs compile-on-import)
    • set ZIG_RELEASEMODE=ReleaseFast|ReleaseSafe|Debug as needed
  3. If you changed stubs/output:
    • ensure src/faebryk/core/zig/gen/** gets updated (this is driven by src/faebryk/core/zig/__init__.py)

Testing

  • Smoke tests are usually through downstream modules:
    • python -m faebryk.core.graph (GraphView allocation/cleanup stress)
    • ato dev test --llm test/core/solver (heavy user of graph + bindings via many subsystems)

Best Practices

  • Assume mistakes segfault: treat changes here like unsafe systems programming.
  • Be explicit about ownership:
    • if a wrapper allocates Zig memory, define how it is freed (explicit .destroy() vs tp_dealloc calling .deinit()).
    • if you duplicate input buffers (sexp does), expose a free(...) path and document it.
  • Don’t rely on Python GC for Zig arenas unless you intentionally installed a tp_dealloc that calls deinit.
  • Stub hygiene matters: keep the .pyi surface accurate; many callers rely on types for navigation.

Build-on-import behavior (important)

src/faebryk/core/zig/__init__.py is responsible for:

  • compiling extensions in editable installs (unless ZIG_NORECOMPILE=1)
  • loading pyzig.so and pyzig_sexp.so from src/faebryk/core/zig/zig-out/lib/
  • copying + formatting generated .pyi files into src/faebryk/core/zig/gen/** (black + ruff)

technical

github
atopile/atopile
stars
3177
license
MIT
contributors
41
last commit
2026-04-03T20:56:37Z
file
.claude/skills/pyzig/SKILL.md

related