Skip to content

happystraw/phpz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

186 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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.1398+cb5635714
  • 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():

    What Registered by When How
    Functions ext_functions Module init Auto: set in module entry struct
    Constants register_{name}_symbols MINIT Auto: called by module_startup_func
    Classes register_class_* MINIT Manual: 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

License

Stars

4 stars

Watchers

0 watching

Forks

Releases

No releases published

Contributors