PHP-FFIの簡単な動作テストは以前にもやったので、今回は色んな引数、色んな戻り値のパターンでサンプル実装を書いてみた。
ネイティブコードの種類としては、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マニュアル。
特にFFI\CData
はネイティブコードとの橋渡しになるデータ型なので要チェック。