ホームページ  >  記事  >  バックエンド開発  >  PHP が C 関数を呼び出せるようにする: FFI 拡張機能 (コード付き)

PHP が C 関数を呼び出せるようにする: FFI 拡張機能 (コード付き)

醉折花枝作酒筹
醉折花枝作酒筹転載
2021-06-09 17:09:442055ブラウズ

この記事では、PHP で C:FFI 拡張機能を呼び出すことができる関数を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

PHP が C 関数を呼び出せるようにする: FFI 拡張機能 (コード付き)

#大企業では、通常、多数のプログラミング言語が存在します。たとえば、Java をマイクロサービス層として使用し、C を基礎となる操作に使用し、PHP を中間層として使用し、最後に JS を使用して効果を表示できます。これらの言語間の連携のほとんどは RPC を通じて完了するか、データがデータベースに直接保存され、別の言語を使用して取得されます。では、PHP コードはこれらの言語を直接呼び出すことができるのでしょうか?実は、PHP には C 言語を直接呼び出すことができる拡張ライブラリが用意されており、この拡張ライブラリは PHP にデフォルトで組み込まれている、FFI 拡張機能です。

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

推奨学習: php ビデオ チュートリアル

以上がPHP が C 関数を呼び出せるようにする: FFI 拡張機能 (コード付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。