Skip to content

Repository files navigation

Phpz - Build PHP Extensions with Zig

A Zig framework for building PHP extensions with PHP C API bindings.

ℹ️ Note: phpz already covers most PHP extension use cases, but the API is still evolving. Pin to a specific commit if you need stability.

Requirements

  • zig: 0.17.0-dev.1552+79dc16a0e
  • php: 8.2-8.5 (NTS/ZTS) on Linux (x86_64/aarch64), macOS (x86_64/aarch64), Windows MSVC (x64)

Features

  • Modules — extension metadata, lifecycle hooks, phpinfo, INI, globals, observers, and exports.
  • Stub integration — arginfo, function entries, constants, attributes, class metadata, and arginfo checks.
  • Functions and methods — typed Ctx arguments, returns, nullable values, raw zvals, and PHP argument errors.
  • Classes and OOP — bind Zig extern struct lifecycles to PHP objects, with class entries, methods, inheritance, interfaces, enums, exceptions, and handlers.
  • Runtime state — typed module globals, PHP/Zend globals, and superglobal access for NTS/ZTS builds.
  • Zval and Zend APIs — zval conversions, ownership helpers, arrays, strings, objects, callables, functions, and resources.
  • INI, phpinfo, and errors — typed INI values, phpinfo helpers, PHP errors, exceptions, and bailout-safe cleanup.
  • Observers — function-call, error, and exception hooks for profiling and monitoring.
  • Memory — PHP-backed Zig allocator with optional debug leak traces.
  • Build integration — PHP C translation, extension linking, and platform-specific setup.

Quick Start

Generate a PHP extension skeleton:

# Generate a new PHP extension skeleton# PHP >= 8.3:
curl -fsSL https://raw.githubusercontent.com/happystraw/phpz/dev/tools/phpz_skel.php \
| php -- --ext my_php_extension
# PHP 8.2:
curl -fsSLO https://raw.githubusercontent.com/happystraw/phpz/dev/tools/phpz_skel.php
php phpz_skel.php --ext my_php_extension
# Run tests (Optional)cd my_php_extension
zig build run-tests

Manual Setup

For a complete minimal project, see examples/skeleton.

1. Add phpz

zig fetch --save git+https://github.com/happystraw/phpz

2. Create the extension files

A phpz extension usually contains:

  • build.zig.zon — declares the phpz dependency
  • build.zig — initializes Phpz and calls phpz.addExtension
  • <name>.stub.php — PHP API declarations
  • <name>_arginfo.h — generated by PHP's gen_stub.php
  • <name>.h — includes phpz.h and the generated arginfo header
  • src/root.zig — registers functions, classes, and the module

3. Generate arginfo

php /path/to/php-src/build/gen_stub.php <name>.stub.php

4. Build

zig build -Dphp-include-dir="$(php-config --include-dir)"

For the complete build.zig, stub.php, header, Zig module, and PHPT tests, use examples/skeleton as the reference.

Examples

Check out the examples/ directory for complete working examples.

How It Works

 Build-time Compile-time Runtime
────────── ──────────── ───────
stub.php Zig source
│ │
│ php-src/build/gen_stub.php │
▼ │
arginfo.h │
[ext_functions] │
[register_class_*] │
[register_{name}_symbols] │
│ │
│ translate-c (zig build) │
▼ ▼
PHP C bindings ─────────────► phpz comptime:
(php_c module) ├─ phpz.function() → zif_* export
├─ Class.method() → zim_* export
├─ phpz.Class(T) → wrapper type
└─ phpz.module() → get_module() export
│
├─── PHP loads .so
│
▼
module_startup [auto]
├─ register_{name}_symbols (constants)
├─ ini_entries
└─ user hook
└─ Class.register() (classes) [manual]
  1. Build-timegen_stub.php generates arginfo.h from .stub.php, containing function metadata and register_* symbols. translate-c converts PHP C headers into Zig bindings.

  2. Compile-timephpz.function() exports zif_* wrappers, phpz.Class() creates wrapper types, phpz.module() exports get_module() for the dynamic loader.

  3. Runtime — PHP loads .soget_module():

    WhatRegistered byWhenHow
    Functionsext_functionsModule initAuto: set in module entry struct
    Constantsregister_{name}_symbolsMINITAuto: called by module_startup_func
    Classesregister_class_*MINITManual: Class.register() in module_startup_fn

    Functions are resolved from the module entry when the extension loads; constants are registered during MINIT via the auto-generated register_{name}_symbols. Classes require an explicit Class.register() call in module_startup_fn — this gives you control over registration order and the opportunity to configure ObjectHandlers or parent classes.

About

Phpz - Build PHP Extensions with Zig (A Zig framework for building PHP extensions with PHP C API bindings.)

Topics

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages