FFI
FFI、Foreign Function Interface、外部関数インターフェイスとは。この拡張機能を使用すると、いくつかのパブリック ライブラリ (.dll、.so) をロードできるようになります。これは、実際には、いくつかの C データ構造と関数を呼び出すことができることを意味します。すでに PHP ソースコードとともにリリースされている拡張機能ですが、コンパイル時に --with-ffi を追加すると、PHP プログラムに直接コンパイルできます。
ここではすでに PHP をコンパイルしているので、この拡張機能を直接見つけて、簡単な拡張機能のインストール手順を実行してインストールを完了します。
cd php-7.4.4/ext/ffi/ phpize ./configure make && make install
インストールが完了したら、php.ini ファイル内の拡張機能を忘れずに開いてください。この拡張機能について注意すべき点の 1 つは、構成項目 ffi.enable があることです。デフォルトでは、この構成項目の値は「preload」であり、CLI SAPI 環境でのみ FFI 機能が有効になります。もちろん、「true」または「false」に変更してオンまたはオフにすることもできます。 「true」に設定すると、この拡張機能がすべての環境で有効になります。
FFI を使用して C 関数を呼び出す
次に、FFI が C 関数を呼び出す方法を簡単に見てみましょう。
// 创建一个 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
2 つのオブジェクトを作成し、それぞれ C の printf() 関数と pow() 関数を呼び出しました。 FFI::cdef() は FFI オブジェクトの作成に使用され、2 つのパラメータを受け取ります。1 つは通常の C 言語の宣言シーケンス (型、構造体、関数、変数など) を含む文字列です。実際には、この文字列は C ヘッダー ファイルからコピーして貼り付けることができます。もう 1 つのパラメータは、ロードおよびリンクされる共有ライブラリ ファイルの名前です。つまり、宣言する文字列に対応する .dll または .so ファイルが必要です。たとえば、libc.so.6 には pow() などの計算関数がないため、数学関連の関数を見つける必要があります。 C言語の計算関数ライブラリです。
変数と配列の定義
もちろん、FFI では変数と配列を定義することもできます。
// 创建一个 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),内存大小
FFI::new() 関数を使用して C データ構造、つまり変数宣言を作成します。これらの変数の内容は cdata 属性に保存されます。配列は、この関数の戻り値を直接操作できます。もちろん、使用を終了したい場合は、C 言語の開発と同じように、FFI::free() を使用して変数を解放する必要があります。
まとめ
とても高級感がありませんか?ただし、FFI によって呼び出される C 関数は、PHP 自体によって呼び出される関数ほど効率的ではないことに注意してください。たとえば、PHP 自体を使用して pow() 関数を使用する方が効率的です。また、FFI 拡張機能は PHP と同時にリリースされましたが、まだ実験段階です。言い換えれば、この拡張機能は将来的に使用される可能性のある他の機能に備えて用意されており、まだ不確実な点が多くあります。したがって、運用環境で同様の機能が必要な場合は、さらに詳細な調査を行う必要があります。
テスト コード:
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