Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

Building Custom PHP Extensions

購入して約1ヶ月放置プレーだったBuilding Custom PHP Extensionsを読み始めました。

Building Custom Php Extensions

Building Custom Php Extensions

まだ読み始めということで、地雷を踏みつつ、少しずつ進めていこうかと思います。

最初のセクションで簡単なPHPモジュールを作っているので、PHP4.3.11でとりあえずやってみました。
流れとしては、用意されているスクリプトで雛形を作成し、それに実装していく感じ。Apacheモジュールも似たようなもの(apxsで作成)なので、違和感はなし。

雛形作成からbuild、動作確認までのざっとした流れは、以下の通り。

$ cd /usr/local/src/php-4.3.11/ext/
$ vi first_test.proto
$ cat first_test.proto
double calcpi(int iterations) Calculate Pi
string reverse(string input) Reverse the input string
array uniquechars(string input [, bool case_sensitive]) Return the unique characters in the string
$ ./ext_skel --extname=first_test \
             --proto=first_test.proto
$ cd first_test
$ cp -p config.m4 config.m4.org
$ vi config.m4
$ diff config.m4.org config.m4
16c16
< dnl PHP_ARG_ENABLE(first_test, whether to enable first_test support,
---
> PHP_ARG_ENABLE(first_test, whether to enable first_test support,
18c18
< dnl [  --enable-first_test           Enable first_test support])
---
> [  --enable-first_test           Enable first_test support])
$ phpize
$ ./configure --enable-first_test
$ make
$ make install
$ 
$ php -f ./first_test.php
Functions available in the test extension:<br>
confirm_first_test_compiled<br>
calcpi<br>
reverse<br>
uniquechars<br>
<br>
Congratulations! You have successfully modified 
ext/first_test/config.m4. Module first_test is 
now compiled into PHP.
$

続けて、php.iniにも

extension=first_test.so

と追記してApacheを再起動。phpinfoを呼び出すと、first_testモジュールが有効になっている旨が(当然)表示されました。

上記の流れで作成されたfirst_test.cには、first_test.protoファイルで定義した関数定義やパラメータチェックなどの基本部分が反映されています。

/* {{{ proto double calcpi(int iterations)
   Calculate Pi */
PHP_FUNCTION(calcpi)
{
    int argc = ZEND_NUM_ARGS();
    long iterations;

    if (zend_parse_parameters(argc TSRMLS_CC, "l", &iterations) == FAILURE) 
        return;

    php_error(E_WARNING, "calcpi: not yet implemented");
}
/* }}} */

なので、以下のように実行してみると、

$ echo '<?php calcpi(10); ?>' | php
Warning: calcpi: not yet implemented in - on line 1
$ 
$ echo '<?php calcpi(); ?>' | php
Warning: calcpi() expects exactly 1 parameter, 0 given in - on line 1
$ 
$ echo '<?php calcpi(1, 2); ?>' | php
Warning: calcpi() expects exactly 1 parameter, 2 given in - on line 1
$ 
$ echo '<?php calcpi(array(10)); ?>' | php
Warning: calcpi() expects parameter 1 to be long, array given in - on line 1
$ 

実装されていないので当然といえば当然ですが、パラメータチェックはちゃんと動作することが確認できます。

うーん。やはりこういった雛形作成ツールって、すげ〜。


今回はphpizeを使っていますが、Building Custom PHP Extensionsではbuildconfを実行するよう記述されていました(ext_skelのヘルプもそう)。が、buildconf自体が作成されませんでした。

もう一つ。
protoオプションには「~」は使えません。内部でsedを使ってる関係ですかね?これで思いっきりはまりました。。。

また、既存のモジュールに新たに関数を追加する場合、ext_skelスクリプトを使って別ファイルに基本部分のコードを生成することができるようです。

$ ./ext_skel --proto=first_test.proto \
             --stubs=first_test/first_test_functions.c