おぎろぐはてブロ

なんだかんだエンジニアになって10年以上

CodeGen_PECL 1.1.0で関数プロトタイプのオプション引数の解析で順番が逆になる

id:Yudoufuさんから教えてもらったのだけれど、

hoge([string hoge1 [,string hoge2] ]) ってpecl-genやったら、できたものがhoge(hoge2, hoge1)になった。。

む?と思って実際に確認してみたら、その通りになりました。

pecl-genコマンドには、関数のプロトタイプをして、その部分だけのスケルトンを生成するオプション(--function)があります。

$ pecl-gen --function="void hoge([string hoge1 [, string hoge2]])"

これを叩くと、関数定義の部分はこのようになり、引数の定義も hoge2, hoge1 と逆になって、zend_parse_parametersにも逆に入っています。これだと、void hoge(string hoge2, string hoge1)の動きになってしまいます。

/* {{{ proto void hoge([string hoge1 [, string hoge2]])
   */
PHP_FUNCTION(hoge)
{
    const char * hoge2 = NULL;
    int hoge2_len = 0;
    const char * hoge1 = NULL;
    int hoge1_len = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &hoge2, &hoge2_len, &hoge1, &hoge1_len) == FAILURE) {
        return;
    }

    php_error(E_WARNING, "hoge: not yet implemented"); RETURN_FALSE;

}
/* }}} hoge */

3つにしてみると、やっぱり逆。

/* {{{ proto void hoge([string hoge1 [, string hoge2 [, string hoge3]]])
   */
PHP_FUNCTION(hoge)
{
    const char * hoge3 = NULL;
    int hoge3_len = 0;
    const char * hoge2 = NULL;
    int hoge2_len = 0;
    const char * hoge1 = NULL;
    int hoge1_len = 0;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sss", &hoge3, &hoge3_len, &hoge2, &hoge2_len, &hoge1, &hoge1_len) == FAILURE) {
        return;
    }

    php_error(E_WARNING, "hoge: not yet implemented"); RETURN_FALSE;

}
/* }}} hoge */

必須引数については、こういう動きはせず、オプション引数の場合にだけで起こっています。

これはバグ (修正済みだけど未リリース)

詳しくは読んでないけれど、それっぽいコメントが入っていたバグ修正が行われていました。

ただ、2008/1/7に修正されたものなので、現在PEARでリリースされているバージョン(1.1.0)には取り込まれていません。オプション引数を複数持つ関数のプロトタイプを書くときは、次のリリースを待つか、パッチあてるか、生成されたコードを手で直すかする必要があります。

[2008/03/22 追記]

3月4日に新しいバージョンがリリースされ、現在最新の1.1.2では修正されています。 (thx id:shimooka)