ホームページ >バックエンド開発 >PHPチュートリアル >PHP 拡張機能と埋め込み -- PHP 拡張機能のパラメーター_PHP チュートリアル
これまでの記事では、関数は受け取るパラメーターと返す型の点で比較的単純ですが、実際にはより複雑になることがよくあります。この記事では主に、PHP 拡張機能の開発においてユーザー空間からパラメーターを受け取り、それに応じてこれらのパラメーターの型、数、その他の情報を確認する方法について説明します。
1. 自動型変換には zend_parse_parameters() を使用します
PHP 拡張機能では、入力パラメーターを取得する最も簡単な方法は、zend_parse_parameters() 関数を使用することです。
この関数の呼び出しの最初の引数は常に ZEND_NUM_ARGS() TSRMLS_CC です。この引数は入力引数の数を int として返します。PHP_FUNCTION(sample_getlong) { long foo; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &foo) == FAILURE) { RETURN_NULL(); } php_printf("The integer value of the parameter you " "passed is: %ld\n", foo); RETURN_TRUE; }は l であり、long 型であるため、それに対応して、事前に long 型の foo パラメータを宣言し、その値を参照渡しします。 以下に、C 言語のパラメータと型のより詳細な対応関係を示します。 b ------ zend_bool l ------- 長い d ------- ダブル s ------- char* 、 int r ------- zval* a ------ zval* o ------ zval* O ----- zval*、zend_class_entry* z ------ zval* Z ----- zval**
function sample_hello_world($name) { echo "Hello $name!\n"; }C 言語では、zend_parse_parameters 関数が使用されます。 れーれー
PHP_FUNCTION(sample_hello_world) { char *name; int name_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { RETURN_NULL(); } php_printf("Hello "); PHPWRITE(name, name_len); php_printf("!\n"); }を呼び出す場合、2 番目のパラメータを指定する必要はありません。 れーれー
りー
強制分離:
変数が関数に渡されるとき、参照によって渡されるかどうかに関係なく、refcount は常に少なくとも 2 になります。1 つはそれ自体であり、もう 1 つは関数に渡されるコピーです。この zval を変更する前に、参照されていないコレクションからそれを分離する必要があります。
この機能は NULL フラグと同じであり、必要な場合にのみ使用されます。
古いバージョンの PHP と互換性を持たせたい場合、またはパラメータを受信するためのキャリアとして zval を使用したいだけの場合は、zend_get_parameters() 関数を使用してパラメータを受信することを検討できます
zend_parse_parameters() と比較すると、解析せずに直接取得されます。型変換は自動的には実行されません。拡張実装のすべてのパラメーターのキャリアは zval です。
リーリー
同時に、受信が失敗してもエラーをスローしません。また、デフォルト値を持つパラメーターを処理することもできません。解析との最後の違いは、コピーオンライトに準拠するすべての zval を自動的に強制的に分離することです。それをコピーして関数内に送信します。
です。
りー
変数パラメータ、任意の数のパラメータを処理します:
ZEND_FUNCTION(var_dump) { int i, argc = ZEND_NUM_ARGS(); zval ***args; args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE) { efree(args); WRONG_PARAM_COUNT; } for (i=0; i<br> 程序首先获取参数数量,然后通过safe_emalloc函数申请相应大小的内存来存储这些zval**的参数。这里使用zend_get_parameters_array_ex()函数来把传递给函数的参数填充到args中。提醒一下,还存在一个zend_get_parameters_array()函数,唯一不同是它将zval*类型的参数填充到args中,并且需要ZEND_NUM_ARGS()作为参数。<br> </p> <p><br> </p> <p><br> </p> <p><strong>2. Arg info参数和类型的绑定</strong></p> <p>这个arg info结构是ZE2才有的。每一个arg info声明都由一个ZEND_BEGIN_ARG_INFO()或ZEND_BEGIN_ARG_INFO_EX()宏组成,后面跟着0个或多个ZEND_ARG_*INFO(), 然后最后以ZEND_END_ARG_INFO()作为结尾。<br> 假定要重写count()函数:<br> </p> <p><pre class="code">PHP_FUNCTION(sample_count_array) { zval *arr; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) { RETURN_NULL(); } RETURN_LONG(zend_hash_num_elements(Z_ARRVAL_P(arr))); }
ZEND_BEGIN_ARG_INFO(php_sample_array_arginfo, 0) ZEND_ARG_ARRAY_INFO(0, "arr", 0) ZEND_END_ARG_INFO() 。。。 PHP_FE(sample_count_array, php_sample_array_arginfo) 。。。
而对于对象来说,也可以通过arg info进行限定:
ZEND_BEGIN_ARG_INFO(php_sample_class_arginfo, 0) ZEND_ARG_OBJECT_INFO(1, "obj", "stdClass", 0) ZEND_END_ARG_INFO()
这里第一个参数被设为1,表示是引用方式传递,但是对象其实在ZE2中都是引用传递的。不要忘记了array和object的allow_null选项。
如果使用的是php4的话,只能用PHP_TYPE_P()进行检查,或使用convert_to_type()方法进行类型转换。