Signatur
Beschreibung
FFI\CData ist eine interne PHP-Klasse, die einen C-Datenwert kapselt, der über die FFI-Erweiterung erzeugt wurde. Instanzen dieser Klasse entstehen beispielsweise durch Aufrufe von FFI::new(), FFI::cast() oder als Rückgabewert aus nativen C-Funktionsaufrufen. Sie können nicht direkt mit new FFI\CData() instanziiert werden.
Je nach zugrunde liegendem C-Typ verhält sich ein CData-Objekt unterschiedlich: Skalare C-Typen (z. B. int, double) können über die Eigenschaft $cdata gelesen und gesetzt werden. Strukturen und Unions ermöglichen den Zugriff auf ihre Felder als PHP-Objekteigenschaften. Arrays erlauben den Zugriff über numerische Indizes wie bei PHP-Arrays.
Zeiger-Typen unterstützen Zeigerarithmetik; ein dereferenzierter Zeiger liefert ebenfalls ein CData-Objekt. Mit FFI::addr() kann die Adresse eines CData-Werts als Zeiger ermittelt werden, mit FFI::cast() lässt sich der Typ neu interpretieren. FFI::free() gibt manuell allokierten Speicher wieder frei.
FFI\CData-Objekte sind besonders nützlich, wenn man aus PHP heraus mit C-Bibliotheken interagiert, die komplexe Strukturen oder Zeiger erwarten – etwa beim Aufruf von Systemfunktionen, Grafikbibliotheken oder beim Verarbeiten von Binärprotokollen mit definierten C-Strukturen.
Beispiele
Skalar-CData lesen und schreiben
<?php
$ffi = FFI::cdef();
// Erzeuge eine C-int-Variable
$val = $ffi->new('int');
echo $val->cdata; // 0 (Standardwert)
$val->cdata = 42;
echo $val->cdata; // 42
C-Struktur mit FFI\CData verwenden
<?php
$ffi = FFI::cdef('
typedef struct {
int x;
int y;
} Point;
');
// Struktur erzeugen und Felder befüllen
$point = $ffi->new('Point');
$point->x = 10;
$point->y = 20;
echo "x = {$point->x}, y = {$point->y}\n";
// Zeiger auf die Struktur ermitteln
$ptr = FFI::addr($point);
echo "Zeiger-x = {$ptr->x}\n";
C-Array mit CData verwenden
<?php
$ffi = FFI::cdef();
// C-Array mit 5 int-Elementen
$arr = $ffi->new('int[5]');
for ($i = 0; $i < 5; $i++) {
$arr[$i] = $i * $i;
}
for ($i = 0; $i < 5; $i++) {
echo $arr[$i] . ' ';
}
Manuell allokierten Speicher freigeben
<?php
$ffi = FFI::cdef();
// Speicher manuell allokieren (owned = false, kein automatisches Freigeben)
$buf = $ffi->new('char[64]', false);
$buf[0] = ord('H');
$buf[1] = ord('i');
echo chr($buf[0]) . chr($buf[1]) . "\n";
// Manuell freigeben
FFI::free($buf);
// Wichtig · Fallstricke
Nicht direkt instanziierbar: FFI\CData-Objekte können nicht mit new FFI\CData() erzeugt werden. Sie entstehen ausschließlich durch die Methoden der FFI-Klasse wie FFI::new() oder FFI::cast().
Speicherverwaltung: Standardmäßig verwaltet PHP den Speicher eines CData-Objekts automatisch (Garbage Collection). Wird FFI::new() mit dem zweiten Parameter false aufgerufen (kein owned), muss der Speicher manuell mit FFI::free() freigegeben werden, andernfalls entsteht ein Speicherleck.
Sicherheit: Die FFI-Erweiterung erlaubt direkten Zugriff auf Speicher und C-Bibliotheken. Fehlerhafte Typkonvertierungen oder Out-of-Bounds-Zugriffe auf C-Arrays können zu Abstürzen oder Sicherheitslücken führen. Im Produktionsbetrieb sollte FFI nur mit sorgfältig geprüftem Code eingesetzt werden. Zudem muss die ffi.enable-INI-Direktive entsprechend konfiguriert sein.
Verfügbarkeit: Die FFI-Erweiterung ist seit PHP 7.4 im Core gebündelt, muss jedoch explizit aktiviert werden (extension=ffi in der php.ini).