Lab 04: FFI & C Bindings

Time: 60 minutes | Level: Architect | Docker: docker run -it --rm php:8.3-fpm bash

Overview

PHP's Foreign Function Interface (FFI) allows calling C functions and manipulating C data structures directly from PHP. This enables integration with system libraries, native performance for critical paths, and access to OS-level APIs.

⚠️ Note: FFI requires PHP compiled with --with-ffi. The standard php:8.3-cli Docker image does not include FFI. Use php:8.3-fpm or build PHP with FFI support. To verify: php -m | grep FFI


Step 1: FFI Setup & Prerequisites

# Check FFI availability
php -m | grep FFI

# If FFI is available:
# FFI

# Enable in php.ini:
# ffi.enable=1   (default: preload — only allow in preloaded scripts)
# ffi.enable=2   (true — allow everywhere, development only)

# For Docker: use php:8.3-fpm which includes FFI
docker run -it --rm php:8.3-fpm bash -c "php -m | grep FFI && echo 'FFI available'"

💡 FFI security model: ffi.enable=preload (default in PHP-FPM) only allows FFI in opcache.preload scripts. Use ffi.enable=true for CLI/development. Never use true in production web contexts.


Step 2: FFI::cdef() — Basic libc Calls

📸 Expected Output (with FFI enabled):


Step 3: FFI Structs & Pointers


Step 4: FFI qsort — Callback Functions

📸 Expected Output:


Step 5: FFI::load() — Header Files


Step 6: Performance Comparison

💡 FFI overhead: Each FFI call has ~100-200ns overhead for type marshaling. For functions like sin(), PHP's built-in is faster. FFI is best for: bulk data processing, manipulating C structs, calling complex library functions not exposed in PHP.


Step 7: Real-World FFI — POSIX Time


Step 8: Capstone — FFI Image Processing Simulation

📸 Expected Output (with FFI enabled):


Summary

Concept
API
Notes

Define C interface

FFI::cdef($header, $lib)

Inline C declarations

Load from .h file

FFI::load('/path/to/header.h')

Include #define FFI_LIB

Allocate C memory

$ffi->new('Type')

Managed (auto-freed)

C heap alloc

FFI::cast('T*', malloc($n))

Manual free required

Pointer

FFI::addr($var)

Returns pointer to variable

Cast type

FFI::cast('int*', $ptr)

Reinterpret cast

Struct field

$struct->field

Direct field access

Array index

$arr[$i]

C array element

Sizeof

FFI::sizeof($type)

C sizeof equivalent

Callbacks

Closure as fn pointer

Requires libffi

Enable FFI

ffi.enable=true in php.ini

Dev only; preload for prod

Last updated