What is FFI?
FFI (Foreign Function Interface) is a PHP extension that allows PHP code to call functions written in other languages like C, Rust, or C++. Lyger uses FFI to execute performance-critical code in Rust while maintaining PHP’s ease of use.FFI became stable in PHP 7.4 and is production-ready in PHP 8.0+
How Lyger Uses FFI
Lyger’sEngine class initializes FFI during application startup and maintains a connection to the Rust library throughout the request lifecycle.
FFI Initialization
The C header defines the interface between PHP and Rust. Every exported Rust function must have a corresponding declaration here.
Function Signatures
C-Compatible Types
FFI requires C-compatible types. Here’s how Lyger maps between PHP, C, and Rust:String Handling
Strings require special handling across the FFI boundary:Zero-Copy Pointers
For large data structures like database results, Lyger uses pointer passing to avoid copying data:Pointer Lifecycle
- Rust executes query and stores results in memory
- Rust returns pointer (memory address) as
unsigned long - PHP holds pointer without copying data
- PHP requests serialization when needed
- Rust serializes and returns JSON string
- PHP frees both JSON string and result set
Why use pointers instead of returning data directly?
Why use pointers instead of returning data directly?
Database result sets can be megabytes in size. Passing them through FFI requires serialization (Rust → C → PHP), which is expensive. By using pointers, the data stays in Rust’s memory until needed, then only the final JSON is copied once.
Error Handling
Lyger wraps all FFI calls in try-catch blocks to handle errors gracefully:Error Scenarios
FFI calls can fail for several reasons:- Library not found: Rust library missing or wrong path
- Symbol not found: Function name mismatch in header
- Type mismatch: Passing wrong data types
- Segmentation fault: Memory corruption in Rust code
- Access violation: Attempting to access freed memory
Performance Considerations
When to Use FFI
FFI adds overhead (~1-10μs per call). Use it for operations where Rust’s performance benefit exceeds the FFI overhead: Good candidates for FFI:- CPU-intensive computations
- Database query execution
- HTTP request parsing
- Data serialization/deserialization
- Cryptographic operations
- Image processing
- Simple string concatenation
- Array manipulations
- Small loops
- One-time initialization code
Batching Operations
Minimize FFI calls by batching operations:Real-World Example
Here’s a complete example using the Cache API:Debugging FFI
Checking FFI Availability
Testing FFI Functions
If FFI calls fail silently, check your PHP error logs. Segmentation faults may not appear in your application output.
Library Compilation
Lyger includes pre-compiled Rust libraries for common platforms. If you need to compile for a different platform:Custom Rust compilation targets
Custom Rust compilation targets
For cross-compilation, you’ll need to install additional targets:
Next Steps
Architecture Overview
Understand the full architecture
Always-Alive Server
Learn about the persistent server
Zero-Copy Database
Explore database optimizations
Cache System
Use the Rust-powered cache