PHP 標準関数のソースを読んでみる
PHP Extensionの勉強をしよー!と言ったものの書き方を覚える前に、標準関数とかってどうやって書かれてるの?ってのが気になってきたので、PHP 5.2.2のソースを読んでみた。
しかし、まず何処に何のファイルが置かれていて、何処に何が書いているのかわからない!
数十分見回ってようやく、ext/standard の下あたりが面白そうだということを発見。
最初は手始めに簡単そうな処理を読みたいので、適当にstring.cを開き、
なんとな〜く目にとまった「strtoupper」を読んでみる。ぶら〜りソース読み旅。
なお、情報の正確さは保証しません。m(_ _)m
PHP_FUNCTION(strtoupper)
ext/standard/string.c
PHP_FUNCTION(strtoupper) { zval **arg; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg)) { WRONG_PARAM_COUNT; } convert_to_string_ex(arg); RETVAL_ZVAL(*arg, 1, 0); php_strtoupper(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value)); }
PHP_FUNCTIONマクロ内に記述された名前がPHP上での関数名となる。
PHP_FUNCTIONについてはこちらのエントリーで詳しく解説してくれている。
おぎろぐはてな - PHP_FUNCTIONマクロ
関数内部でreturn_valueとか参照されているけどマクロ内に書かれているのね。
php上でreturnする値はreturn_valueに突っ込めばよさそう。
PHP_FUNCTION(strtoupper) の中
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg)) { WRONG_PARAM_COUNT; }
あたりでPHP上で渡された引数のチェックをして
convert_to_string_ex(arg);
文字列への強制的な変換を行います。文字列が渡された場合は何もしません。 NULL 値は空の文字列に変換されます。Boolean TRUE は "1"、それ以外の Boolean は空の文字列となります。 long および double はそれぞれ対応する文字列表現に変換されます。 配列は "Array"、オブジェクトは "Object" という文字列に変換されます。
ということで引数を無理やり文字列にして*1
RETVAL_ZVAL(*arg, 1, 0); // Zend/zend.h: #define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor) #define ZVAL_ZVAL(z, zv, copy, dtor) { \ int is_ref, refcount; \ is_ref = (z)->is_ref; \ refcount = (z)->refcount; \ *(z) = *(zv); \ if (copy) { \ zval_copy_ctor(z); \ } \ if (dtor) { \ if (!copy) { \ ZVAL_NULL(zv); \ } \ zval_ptr_dtor(&zv); \ } \ (z)->is_ref = is_ref; \ (z)->refcount = refcount; \ }
詳細は見てないけど、引数の文字列を戻り値にコピーして
php_strtoupper(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value)); // Zend/zend_operators.h #define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p) #define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p) #define Z_STRVAL(zval) (zval).value.str.val #define Z_STRLEN(zval) (zval).value.str.len
文字列と長さを引数に、php_strtoupper()という関数を呼びだす。
*php_strtoupper
PHPAPI char *php_strtoupper(char *s, size_t len) { unsigned char *c, *e; c = s; e = c+len; while (c < e) { *c = toupper(*c); c++; } return s; }
内部の処理自体はあまりに普通なので何故か安心した…。
他にもいろいろ読んで少しずつ理解していこう。
今後もこの企画が続く。…かは知らない。
*1:echoった時とかにArrayと表示しやがるのはこいつのパワーか!