PHP-FFIの使い方サンプル書いた

2019-11-22
PHP
FFI
PHP7.4

PHP-FFIの簡単な動作テストは以前にもやったので、今回は色んな引数、色んな戻り値のパターンでサンプル実装を書いてみた。

hanhan1978/php-ffi-samples
php-ffi-samples

ネイティブコードの種類としては、C言語・Go言語の2種類を用意しました。
Goについては、Callbackとか一部未実装ですが、そのうち拡充しておきます。

引数、戻り値のパターン

引数 戻り値
int int
double double
string string
int[] int[]
string[] string[]
callback, int callback, int
callback, double callback, double
struct struct

まとめ

サンプルコードを書いてみた感想としては、とにかくIFはC言語のデータ型に極力合わせるのが良いということです。
intなどを値渡しする場合を除いて、ポインターでのやり取りになるので、戻り値でポインターをもらった場合は、メモリの解放が必要になるので面倒くさいです。

Goについては、CGOというライブラリを使うことで、比較的簡単にかけるのですが、sliceは若干手強いです。Go側はSliceで受け取らないと面倒くさいし、FFI側はCのコードを基準にして作られているので、下手にSlice(CGOがラップしたGoSliceという構造体)を受け取るとseg faultになります。結果としては、Goに渡す時はGoSlice、PHP-FFIに戻す時はCの配列みたいな形を取るのが、一番安定しました。

PHPのClosureをCallbackにそのまま突っ込めるのは魅力的だったのですが、パフォーマンスという点ではいまいちでした。柔軟なIFという点では魅力的ですがClosure内での計算量が多いパターンは速度は上がらないです。この辺はGDBでデバッグしてみると面白そう。

参考

基本的に現状で最も参考になるのはPHPマニュアル。

PHP:FFI Manual

特にFFI\CDataはネイティブコードとの橋渡しになるデータ型なので要チェック。