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 変数へのポインタ。ここに、ユーザーへの戻り値を設定します。
デフォルトの型は IS_NULL です。
|
RETVAL_*, RETURN_* |
zval **return_value_ptr |
PHP に参照を返すときには、ここに変数へのポインタを設定します。 参照を返すことはお勧めしません。 | |
zval *this_ptr |
メソッド呼び出しの場合は、$this オブジェクトを保持する PHP 変数を指します。
|
getThis() |
int return_value_used |
返り値を呼び出し元が使うかどうかを示すフラグ。 |
For clarity, the fully expanded declaration for PHP_FUNCTION(hackers_function) looks like:
void zif_hackers_function(int ht, zval* return_value, zval** return_value_ptr, zval* this_ptr, int return_value_used)
The precense of this_ptr may be confusing, classes are covered in detail in later sections,
suffice to say that PHP_METHOD(MyClass, hackersFunction) would result in the following declaration:
void zim_MyClass_hackersFunction(INTERNAL_FUNCTION_PARAMETERS)
hackers_function doesn't do anything useful, it accepts a number using the zend_parse_parameters API, doubles it, and returns it to the engine.
It is obvious that a normal function would have to do something more complex than double the input, for the purposes of education we are keeping it simple.
On entry to the function return_value is allocated and initialized to null, making null the default return value of any function in PHP.
If zend_parse_parameters does not recieve what is specified by the Hacker as the correct arguments, and the arguments recieved cannot be converted
to conform with type_spec an error will be raised, and by convention, the Hacker should return immediately.
注意:
Arrays,Objects, andResourcescannot be converted.
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_parameteris available from version 5.5, it behaves likezend_parse_parameters_exexcept that instead of reading the arguments from the stack, it receives a single zval to convert, which may be changed in place.
注意:
flagsis intended to be a mask, currently onlyZEND_PARSE_PARAMS_QUIETwill have any impact (supress warnings)
The variable arguments recieved by these API functions are expected to be the address of C variables, and should be considered the output of the zend_parse_parameters API functions.
| Spec | Type | Locals |
|---|---|---|
| a | array |
zval* |
| A | array or 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 or object |
HashTable* |
| l | long |
long |
| L | long (limits out-of-range LONG_MAX/LONG_MIN) |
long |
| o | object |
zval* |
| O | object (of specified zend_class_entry) |
zval*, zend_class_entry* |
| p | string (a valid path) |
char*, int |
| r | resource |
char* |
| s | string |
char*, uint |
| z | mixed |
zval* |
| Z | mixed |
zval** |
注意:
Where the type specifier is
O, the localzend_class_entry*is to be considered input (part of the type spec) tozend_parse_parameter
| Spec | Description |
|---|---|
| * | a variable number of argument of the preceeding type, 0 or more |
| + | a variable number of argument of the preceeding type, 1 or more |
| | | indicates that the remaining parameters are optional |
| / | SEPARATE_ZVAL_IF_NOT_REF on the parameter it follows |
| ! |
the preceeding parameter can be of the specified type or null
For 'b', 'l' and 'd', an extra argument of type zend_bool* must be passed after
the corresponding bool*, long* or double*
addresses which will be set true if null is recieved.
|
注意:
Consult
README.PARAMETER_PARSING_APIincluded in source distributions for more information on parsing parameters
Once the Hacker's function has executed whatever it was implemented to execute, it is time to set the return_value for the engine.
The RETURN_ and RETVAL_ macros are just wrappers around Z_*_P macros that work with return_value.
注意:
RETURN_macros cause execution to leave the function immediately (ie:return;), whileRETVAL_macros allow execution to continue afterreturn_valuehas been set.
The Hacker should now have a reasonable understanding of the anatomy of a function, and to some degree, the anatomy of a method.