DELAEMON BLOG

Live as if you were to die tomorrow. Learn as if you were to live forever.

PHP Extensionの作り方 その2 引数・返り値編

引数と返り値がなければ、やりたいことできなくね?
前回(その1基本編)で作った関数に引数を追加してみる。
スカラ型は楽に扱えるけど、配列・リソースは少しコードが長くなるので省略。

php-src/ext/delaemon/delaemon.c

引数の定義

/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO(arginfo_delaemon, 0)
  ZEND_ARG_INFO(0, arg_int)
  ZEND_ARG_INFO(0, arg_str)
ZEND_END_ARG_INFO()
/* }}} */

関数と引数の紐付け

const zend_function_entry delaemon_functions[] = {
  PHP_FE(confirm_delaemon_compiled,>NULL)   /* For testing, remove later. */
  PHP_FE(delaemon,  arginfo_delaemon)   /* ←ここ */
  PHP_FE_END>-/* Must be the last line in delaemon_functions[] */
};

関数の実装

PHP_FUNCTION(delaemon)
{
  long arg_int, arg_str_len;
  char *arg_str;
  char res[100];

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &arg_int, &arg_str, &arg_str_len) == FAILURE)  {
    return;
  } /*ここで呼び出しもとで渡した引数を受け取ってる*/

  sprintf(res, "arg1 = %ld, arg2 = %s", arg_int, arg_str);
  RETURN_STRING(res, 1); /*返り値用マクロ、他の型のも定義されてる*/
}

zend_parse_parametersでstrを受け取るときはバイト数も返されるので入れ物が必要。
何気にハマった。

テスト用のPHPファイル

cat test_call.php 
<?php
dl('delaemon.so');
$res = delaemon(5, 'Rock');
var_dump($res);
?>

実行する

$ php test_call.php            
string(21) "arg1 = 5, arg2 = Rock"

以上。

実装したい内容がわかっていれば、それと類似している
ことをやっていそうな組み込み関数の実装を調べると
マクロやzend_xxx系メソッドの使い方など色々と参考になると思います。