&reftitle.examples;
FFI の基本的な使い方
FFI API の詳細に深く立ち入る前に、よくあるタスクに対する FFI API の使い方が
どれほど簡単かを示す例をいくつか見てみましょう。
これらの例の中には、libc.so.6 を必要とするものがあります。
それらは、このライブラリが利用できないシステムでは動きません。
共有ライブラリの関数を呼ぶ
printf("Hello %s!\n", "world");
?>
]]>
&example.outputs;
C の関数のうちのいくつかは、特定の呼び出し規約 (例: __fastcall、
__stdcall、,__vectorcall など) を必要とすることに注意してください。
関数を呼び出し、構造体を引数経由で返す
new("struct timeval");
$tz = $ffi->new("struct timezone");
// C の gettimeofday() を呼ぶ
var_dump($ffi->gettimeofday(FFI::addr($tv), FFI::addr($tz)));
// C のデータ構造のフィールドにアクセスする
var_dump($tv->tv_sec);
// C のデータ構造全体を出力する
var_dump($tz);
?>
]]>
&example.outputs.similar;
int(0)
["tz_dsttime"]=>
int(0)
}
]]>
既存の C の変数にアクセスする
errno);
?>
]]>
&example.outputs;
C の変数を作成して書き換える
cdata);
// 単純な代入
$x->cdata = 5;
var_dump($x->cdata);
// 複合代入
$x->cdata += 2;
var_dump($x->cdata);
?>
]]>
&example.outputs;
C の配列を扱う
]]>
&example.outputs;
C の enum を扱う
ZEND_FFI_SYM_TYPE);
var_dump($a->ZEND_FFI_SYM_CONST);
var_dump($a->ZEND_FFI_SYM_VAR);
?>
]]>
&example.outputs;
PHP のコールバック
PHP のクロージャを、関数ポインタ型のネイティブ変数に代入したり、
関数の引数として渡したりできます。
PHP の Closure を C の関数ポインタに代入する
zend_write;
$zend->zend_write = function($str, $len) {
global $orig_zend_write;
$orig_zend_write("{\n\t", 3);
$ret = $orig_zend_write($str, $len);
$orig_zend_write("}\n", 2);
return $ret;
};
echo "Hello World 2!\n";
$zend->zend_write = $orig_zend_write;
echo "Hello World 3!\n";
?>
]]>
&example.outputs;
これは動作こそしますが、この機能は libffi が動作するすべてのプラットフォームでサポートされているわけではありません。
また、非効率的であり、リクエストの終了時にリソースがリークします。
したがって、PHP のコールバックの使用は最小限にすることを推奨します。
PHP/FFI/事前ロードの完全な例
php.ini
preload.php
]]>
dummy.h
dummy.php
printf($format, ...$args);
}
}
?>
]]>
test.php
printf("Hello %s!\n", "world");
?>
]]>