native-code

NIF (Native Implemented Functions) development and SIMD patterns for Elixir/BEAM. TRIGGER when: writing NIFs in C or Rust (Rustler), using erl_nif.h, Zig SIMD code for BEAM integration, tree-sitter grammar NIFs, or discussing native performance boundaries in Elixir. DO NOT TRIGGER when: general C/Zig/Rust language questions (use droo-stack), general Elixir patterns (use droo-stack), Raxol framework (use raxol skill).

native-code

Domain knowledge for building native extensions for the BEAM VM. Covers the NIF boundary (C and Rust), SIMD via Zig, and the cross-cutting concerns that apply regardless of implementation language.

For general language patterns (C, Zig, Rust), see droo-stack.

What You Get

  • NIF boundary patterns (C erl_nif.h, Rust Rustler, Zig SIMD)
  • Scheduler contract and memory model rules
  • Elixir-side module structure for NIF wrappers
  • Common crash/leak patterns and fixes
  • Two-level testing strategy (native unit + ExUnit boundary)

When to use

  • Writing or reviewing NIF code (C erl_nif.h or Rust Rustler)
  • Integrating Zig SIMD routines into BEAM via C ABI
  • Designing the Elixir-side module for a NIF
  • Debugging scheduler issues, memory leaks, or crashes at the native boundary
  • Building tree-sitter grammar parsers as NIFs
  • Setting up precompiled NIF releases

When NOT to use

  • General C, Zig, or Rust coding -- use droo-stack
  • General Elixir patterns -- use droo-stack
  • Raxol TUI framework -- use raxol skill

Reading guide

Working onRead
Scheduler contract, memory model, deploymentreferences/boundary-patterns
Elixir-side NIF module structurereferences/nif-elixir
C NIFs (erl_nif.h, resources, tree-sitter)references/nif-c
Rust NIFs (Rustler, ResourceArc, safety)references/nif-rust
Zig SIMD (@Vector, reductions, NIF integration)references/simd-zig

Key principles

  1. Never block the BEAM scheduler -- NIFs must return within 1ms or use dirty schedulers
  2. The BEAM owns terms, you own native memory -- never store ERL_NIF_TERM across NIF calls
  3. Crash in NIF = crash the entire VM -- no panics (Rust), no segfaults, no undefined behavior
  4. Test at two levels -- native unit tests (cargo test, zig test) AND ExUnit boundary tests
  5. Zero-copy where possible -- use BEAM binaries for large data transfer

Common pitfalls

MistakeImpactFix
NIF takes >1ms without dirty schedulerScheduler starvation, latency spikesAdd ERL_NIF_DIRTY_JOB_CPU_BOUND or schedule = "DirtyCpu"
Storing ERL_NIF_TERM in native structUse-after-free, undefined behaviorCopy data out of terms, or use enif_make_copy with a process-independent env
Rust panic! / unwrap() inside NIFEntire BEAM VM crashesUse Result, catch panics at boundary with std::panic::catch_unwind
Missing NIF stub in Elixir moduleSilent nil return or confusing errorStub must raise "NIF not loaded"
Not freeing native resourcesMemory leak proportional to call rateRegister destructors via resource types

See also

  • droo-stack -- C, Zig, Rust language patterns
  • raxol -- Elixir TUI framework (potential NIF consumer)
  • nix -- packaging native deps with Nix (buildRustPackage, mkDerivation)