PHP エクステンションでの引数の受取り方

PHP エクステンションでの引数の扱い方

PHP エクステンションで自前の関数を作った場合、当然ながら何らかのデータを PHP スクリプトから受け取りたい場合があります。 また、処理内容によって適切な戻り値も返すことができないといけません。

まずは、引数の受け取り方をみてみましょう。

引数の受け取り方

PHP エクステンションにて、引数の数を受け取るためには ZEND_NUM_ARGS() マクロを利用します。

引数を解析するための関数として、次の二つの関数が利用可能です。

int zend_parse_parameters( int num_args TSRMLS_DC, char *type_spec, ... );
int zend_parse_parameters_ex( int flags, int num_args TSRMLS_DC, char *type_spec, ...);

TSRMLS_DC は ZTS (Zend Thread Safety) と非 ZTS の両方に対応するために定義されているマクロです。 TSRM はスレッドセーフリソースマネージャ (Thread Safe Resource Manager)、LS はローカルストレージ (Local Storage) を意味しています。 それぞれのバージョンに対応するビルドに対応するために、以下のようにいくつかマクロが定義されています。
  TSRMLS_C tsrm_ls
  TSRMLS_D void ***tsrm_ls
  TSRMLS_CC , tsrm_ls
  TSRMLS_DC , void ***tsrm_ls

zend_parse_parameters と _ex の違いは第一引数でフラグを受け取るかどうかだけです。 ここでは zend_parse_parameters のみに着目します。

第一引数はパラメータの数です。これは前述の通り ZEND_NUM_ARGS() マクロで取得できます。

ポイントは第二引数の type_spec です。

type_spec に、下記のような指定文字 (specification character) と指定修飾子 (specification modifier) を記述することによって、どのようなパラメータを期待しているのか記述します。

指定文字意味
llong
ddouble
sstring (NULL 終端) 及びその長さ
bboolean (zend_bool)
rリソース (zval)
a配列
oオブジェクト
Oオブジェクト (クラスエントリによる型指定)
zzval
修飾子意味
|この修飾子以後のパラメータは任意であることを示す。
/この修飾子以後の直前のパラメータは呼び出し側と切り離される。 これはパラメータの値を変更するが、呼び出し元側ではその変更が反映されないようにしたい場合に指定する。
!この修飾子は zval パラメータ (a, o, O, z) にのみ適用され NULL に指定可能であることを示す。

例1: 例えば文字列をひとつ受け取る場合は、次のようにします。

ZEND_FUNCTION(keicode_param1) {

     int argc;
     int arg_len;
     char *arg = NULL;

     argc = ZEND_NUM_ARGS();

     if( FAILURE == zend_parse_parameters( 
               argc TSRMLS_CC, 
               "s/", 
               &arg, &arg_len ) ) {
          return;
     }

     OutputDebugString( arg );

}

文字列をひとつ受け取りたいだけなのですが、s を指定する場合は、文字列へのポインタに加えて、 その長さを受け取るための整数の変数の参照も渡す必要があります。そのため、zend_parse_parameters には &arg と &arg_len の二つを渡しています。

上の関数を次のように呼ぶと、以下のスクリーンショットのようにデバッグトレースに、 確かに引数で渡された文字が表示されました。

<?php
keicode_param1( 'Hello!' );
?>

例2: 第一引数と第二引数それぞれに、文字列と倍精度実数 (double) を受け取り、第二引数の double はオプションにする場合は、以下のようにします。

     int argc;
     int arg_len;
     char *arg = NULL;
     double dbl = 123.0;
     
     argc = ZEND_NUM_ARGS();

     if( FAILURE == zend_parse_parameters( 
               argc TSRMLS_CC, 
               "s/|d", 
               &arg, &arg_len, &dbl ) ) {
          return;
     }

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説