Skip to main content

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’s Engine 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:
Always call the appropriate free function after copying strings from Rust to PHP. Failing to do so causes memory leaks.

Zero-Copy Pointers

For large data structures like database results, Lyger uses pointer passing to avoid copying data:

Pointer Lifecycle

  1. Rust executes query and stores results in memory
  2. Rust returns pointer (memory address) as unsigned long
  3. PHP holds pointer without copying data
  4. PHP requests serialization when needed
  5. Rust serializes and returns JSON string
  6. PHP frees both JSON string and result set
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
Always provide fallback implementations for critical functionality. Never let FFI errors crash your application.

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
Poor candidates for FFI:
  • 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:
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