Was ist FFI?
FFI, Foreign Function Interface, Fremdfunktionsschnittstelle. Mit dieser Erweiterung können wir einige öffentliche Bibliotheken (.dll, .so) laden, was tatsächlich bedeutet, dass wir einige C-Datenstrukturen und -Funktionen aufrufen können. Es handelt sich bereits um eine Erweiterung, die mit dem PHP-Quellcode veröffentlicht wurde. Sie können beim Kompilieren --with-ffi hinzufügen, um sie direkt in das PHP-Programm zu kompilieren.
Wir haben PHP hier bereits kompiliert, daher finden wir diese Erweiterung direkt und führen einfache Installationsschritte für die Erweiterung durch, um die Installation abzuschließen.
cd php-7.4.4/ext/ffi/ phpize ./configure make && make install
Denken Sie nach Abschluss der Installation daran, die Erweiterung in der Datei php.ini zu öffnen. Bei dieser Erweiterung ist zu beachten, dass sie über ein Konfigurationselement ffi.enable verfügt. Standardmäßig ist der Wert dieses Konfigurationselements „preload“, wodurch nur FFI-Funktionen in der CLI-SAPI-Umgebung aktiviert werden. Natürlich können wir es auch in „true“ oder „false“ ändern, um es ein- und auszuschalten. Durch die Einstellung „true“ wird diese Erweiterung in allen Umgebungen aktiviert.
Verwenden Sie FFI, um C-Funktionen aufzurufen
Als nächstes werfen wir einen kurzen Blick darauf, wie es C-Funktionen aufruft.
// 创建一个 FFI 对象,加载 libc 并且导入 printf 函数 $ffi_printf = FFI::cdef( "int printf(const char *format, ...);", // C 的定义规则 "libc.so.6"); // 指定 libc 库 // 调用 C 的 printf 函数 $ffi_printf->printf("Hello %s!\n", "world"); // Hello World // 加载 math 并且导入 pow 函数 $ffi_pow = FFI::cdef( "double pow(double x, double y);", "libboost_math_c99.so.1.66.0"); // 这里调用的是 C 的 pow 函数,不是 PHP 自己的 echo $ffi_pow->pow(2,3), PHP_EOL; // 8
Wir haben zwei Objekte erstellt und die Funktionen printf() und pow() von C aufgerufen. FFI::cdef() wird zum Erstellen eines FFI-Objekts verwendet. Es empfängt zwei Parameter, einer ist eine Zeichenfolge, die die Deklarationssequenz der regulären C-Sprache enthält (Typ, Struktur, Funktion, Variable usw.). Tatsächlich kann diese Zeichenfolge aus der C-Header-Datei kopiert und eingefügt werden. Der andere Parameter ist der Name der gemeinsam genutzten Bibliotheksdatei, die geladen und verknüpft werden soll. Das ist die .dll- oder .so-Datei, die wir benötigen, die der von uns deklarierten Zeichenfolge entspricht. In libc.so.6 gibt es beispielsweise keine Berechnungsfunktion wie pow(), daher müssen wir das mathematisch bezogene C finden Bibliothek für Sprachberechnungsfunktionen.
Variablen und Arrays definieren
Natürlich kann FFI auch Variablen und Arrays definieren.
// 创建一个 int 变量 $x = FFI::new("int"); var_dump($x->cdata); // int(0) // 为变量赋值 $x->cdata = 5; var_dump($x->cdata); // int(5) // 计算变量 $x->cdata += 2; var_dump($x->cdata); // int(7) // 结合上面的两个 FFI 对象操作 echo "pow value:", $ffi_pow->pow($x->cdata, 3), PHP_EOL; // pow value:343 $ffi_printf->printf("Int Pow value is : %f\n", $ffi_pow->pow($x->cdata, 3)); // Int Pow value is : 343.000000 // 创建一个数组 $a = FFI::new("long[1024]"); // 为数组赋值 for ($i = 0; $i < count($a); $i++) { $a[$i] = $i; } var_dump($a[25]); // int(25) $sum = 0; foreach ($a as $n) { $sum += $n; } var_dump($sum); // int(523776) var_dump(count($a)); // int(1024) 数组长度 var_dump(FFI::sizeof($a)); // int(8192),内存大小
Verwenden Sie die Funktion FFI::new(), um eine C-Datenstruktur, also eine Variablendeklaration, zu erstellen, und der Inhalt dieser Variablen wird im cdata-Attribut gespeichert. Das Array kann direkt mit dem Rückgabewert dieser Funktion arbeiten. Wenn wir die Verwendung beenden möchten, müssen wir natürlich immer noch FFI::free() verwenden, um die Variablen freizugeben, genau wie bei der C-Sprachentwicklung.
Zusammenfassung
Fühlt es sich nicht sehr edel an? Bitte beachten Sie jedoch, dass die von FFI aufgerufenen C-Funktionen nicht so effizient sind wie die von PHP selbst aufgerufenen. Mit dieser pow()-Funktion ist es beispielsweise effizienter, PHP selbst zu verwenden. Obwohl die FFI-Erweiterung gleichzeitig mit PHP veröffentlicht wurde, ist sie darüber hinaus noch experimentell. Mit anderen Worten: Diese Erweiterung ist für andere Funktionen vorbereitet, die möglicherweise in Zukunft verwendet werden, und es bestehen noch viele Unsicherheiten. Wenn Sie also ähnliche Funktionen in einer Produktionsumgebung benötigen, müssen Sie noch eingehendere Recherchen durchführen.
Testcode:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202004/source/%E8%AE%A9PHP%E8%83%BD%E5%A4%9F%E8%B0%83%E7%94%A8C%E7%9A%84%E5%87%BD%E6%95%B0-FFI%E6%89%A9%E5%B1%95.php