関数の作成
PHP では関数とメソッドはだいたい同じ形式で、メソッドは単にスコープが限定された関数でしかありません。 つまり、そのメソッドが属するクラスエントリのスコープになるということです。 クラスエントリについては、このマニュアルの別のページで説明します。 このセクションの目的は、関数やメソッドの内部構造を紹介することです。 関数を定義したり、変数を受け取ったり、PHP プログラマーに値を返したりする方法を説明します。
関数の内部構造は、それほど単純ではありません。
PHP_FUNCTION(hackers_function) { /* 受け取る引数をここで指定します */ long number; /* 引数を受け取ります */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &number) != SUCCESS) { return; } /* 何かの作業をします */ number *= 2; /* 戻り値を設定します */ RETURN_LONG(number); }
プリプロセッサの PHP_FUNCTION(hackers_function)
命令は、
次のような宣言に展開されます。
void zif_hackers_function(INTERNAL_FUNCTION_PARAMETERS)
INTERNAL_FUNCTION_PARAMETERS
はマクロとして定義されており、
次の表のようになります。
型と名前 | 説明 | アクセス用マクロ |
---|---|---|
int ht
|
ユーザーから実際に渡されたパラメータの数 | ZEND_NUM_ARGS()
|
zval *return_value
|
PHP 変数へのポインタ。ここに、ユーザーへの戻り値を設定します。
デフォルトの型は |
RETVAL_* , RETURN_*
|
zval **return_value_ptr
|
PHP に参照を返すときには、ここに変数へのポインタを設定します。
参照を返すことはお勧めしません。 |
|
zval *this_ptr
|
メソッド呼び出しの場合は、$this オブジェクトを保持する PHP 変数を指します。
|
getThis()
|
int return_value_used
|
返り値を呼び出し元が使うかどうかを示すフラグ。 |
明確にするために、完全に展開した PHP_FUNCTION(hackers_function)
のドキュメントを示します。
void zif_hackers_function(int ht, zval* return_value, zval** return_value_ptr, zval* this_ptr, int return_value_used)
this_ptr
の存在を奇妙に感じるかもしれません。クラスの詳細は後ほど説明するとして、ここでは
PHP_METHOD(MyClass, hackersFunction)
の結果が次のような宣言になることを示しておけば十分でしょう。
void zim_MyClass_hackersFunction(INTERNAL_FUNCTION_PARAMETERS)
hackers_function
は特に凝ったことをするわけではなく、zend_parse_parameters
API
を使って受け取った数値を二倍して、それをエンジンに返すだけです。
普通は、単に入力を二倍するだけなどではなく、もっと複雑な何かを行うことでしょう。
ここでは、説明のために、できるだけシンプルにとどめました。
関数に入った際に return_value
を確保し、null
に初期化されます。
これで、PHP の関数のデフォルトの返り値が null
となります。
Hacker
が正しい引数として指定する内容を
zend_parse_parameters
が受け取れず、受け取った引数を
type_spec
を満たす形式に変換できなかった場合は、エラーを発生させます。
そして、Hacker
はその場で return
しなければいけません。
注意:
Array
、Object
、そしてResource
は変換できません。
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, ...)
|
int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...)
|
注意:
zend_parse_parameter
はバージョン 5.5 以降で使用可能で、zend_parse_parameters_ex
と同じような挙動です。 ただ、引数をスタックから読み込むのではなく、変換対象の zval を受け取って、その場で変換します。
注意:
flags
はマスクとして扱うことを想定しています。現時点で有効なフラグはZEND_PARSE_PARAMS_QUIET
だけです (これは、警告を抑制します)。
これらの API 関数から受け取る可変引数は、C の変数のアドレスであることが期待されています。
また、zend_parse_parameters
API 関数の出力であると考えなければいけません。
指定子 | 型 | ローカル |
---|---|---|
a | array
|
zval*
|
A | array あるいは object
|
zval*
|
b | boolean
|
zend_bool
|
C | class
|
zend_class_entry*
|
d | double
|
double
|
f | function
|
zend_fcall_info* , zend_fcall_info_cache*
|
h | array
|
HashTable*
|
H | array あるいは object
|
HashTable*
|
l | long
|
long
|
L | long (LONG_MAX/LONG_MIN の範囲に収まるもの)
|
long
|
o | object
|
zval*
|
O | object (指定した zend_class_entry のもの)
|
zval* , zend_class_entry*
|
p | string (有効なパス)
|
char* , int
|
r | resource
|
zval*
|
s | string
|
char* , int
|
z | mixed
|
zval*
|
Z | mixed
|
zval**
|
注意:
型指定子が
O
の場合、ローカルのzend_class_entry*
はzend_parse_parameter
への入力 (型指定子の一部) と見なされます。
指定子 | 説明 |
---|---|
* | 直前の型の引数が 0 個以上 |
+ | 直前の型の引数が 1 個以上 |
残りのパラメータは任意である | |
/ | 後に続くパラメータを SEPARATE_ZVAL_IF_NOT_REF します。
|
! | 直前のパラメータが、指定した型あるいは null のどちらかになるものとします。
'b'、'l'、'd' の場合は、対応する |
注意:
パラメータのパースについての詳細は、ソース配布物に含まれる
README.PARAMETER_PARSING_API
を参照ください。
一度 Hacker
の関数が実行されたら、実行するよう実装されているかどうかにかかわらず、エンジン向けの return_value
を設定します。
RETURN_
マクロと RETVAL_
マクロは
Z_*_P
の単なるラッパーで、return_value
と組み合わせて使います。
注意:
RETURN_
マクロはその場で関数の実行を終了します (つまり、return;
します) が、RETVAL_
は、return_value
を設定してからも実行を続けます。
これで、関数の仕組みについて、それなりに理解できたことでしょう。 メソッドの仕組みについても、ある程度は理解できたはずです。