最近やってること
PHP Extensionの関数の中で、あたかも関数スコープをもたせること。
Cで、このように書くと
PHP_FUNCTION(hogehoge) { zend_eval_string("echo 'hello world';", NULL, "hoge" TSRMLS_CC); }
これとほぼ等価。
<?php function hogehoge() { eval "echo 'hello world';"; // ↑ 結局 echo 'hello world'; } ?>
なのだけれど、Cの方は、関数スコープに入るわけではない。呼び出し前のスコープと同じレベルで動作する。
要は、
<?php function hogehoge() { $b = 2; var_dump(get_defined_vars()); } $a = 1; hogehoge(); ?>
というコードを上のようなコードで用意したときに、PHPスクリプトでは、
$ php tmp.php array(1) { ["b"]=> int(2) }
なのだけれど、Cのextensionでの関数は、$aも$bも含まれるし、関数を抜けたあとも、$bが残る。
なんでそういう仕様なのかというと、ふつうに「そういうことをしないから」。evalしてたらCで書く意味ないし、PHPスクリプトレベルの変数を直接読み書きすることもないので、汚染の問題もないから。(こんな感じで引数を受け取る)
と、長くなったけど、スコープを作るには、EG(active_symbol_table)を待避させればよい。
- EG(active_symbol_table)のポインタを待避
- HashTableを作成、初期化して、EG(active_symbol_table)にアロケート
- コード実行 (スコープの中)
- 作ったシンボルテーブルを破棄
- EG(active_symbol_table)のポインタを戻す
で、それはできた。(ようにみえるけど、スーパーグローバルとか大丈夫か不安。。)
さらに、EG(function_table)に関数テーブルがあるんだけれど、これ待避させたら、そのスコープだけに存在する関数を定義できる?
と思って、試してたのだけれど、まだうまく動かない。。。
#実行環境でないので、コード間違えてるかも