Start · Sprachen · PHP · Referenz · FFI\CData

FFI\CData

Klasse

Repräsentiert einen nativen C-Datenwert, der über die <code>FFI</code>-Schnittstelle erzeugt und wie reguläre PHP-Daten verwendet werden kann.

seit PHP 7.4.0 Kategorie: misc

Signatur

class FFI\CData

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
0 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";
x = 10, y = 20 Zeiger-x = 10

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] . ' ';
}
0 1 4 9 16

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);
Hi

// 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).