[翻訳][php 拡張機能と埋め込み] 第 7 章 - パラメータの受け入れ
完全な翻訳コンテンツ PDF ドキュメントのダウンロード アドレス: http://download.csdn.net/detail/lgg201/5107012
この本は現在、laruence (http://www.laruence.com) と walu (http://www.walu.cc) によって github 上で翻訳されています。翻訳プロジェクトのアドレスは https://github.com です。 /walu/phpbook
Github 上のこの本のアドレス: https://github.com/goosman-lei/php-eae
将来的には、この本は独立したバージョンを保持したまま、部分的に phpbook プロジェクトに統合される可能性があります。
元のタイトル:
原作者:サラ・ゴーレモン
翻訳者: goosman.lei (Lei Guo)
翻訳者のメールアドレス: lgg860911@yahoo.com.cn
翻訳者ブログ: http://blog.csdn.net/lgg201
権利表明
この翻訳は、いかなる利益も得ることなく、制限なく自由に配布することができます。
いくつかの「プレビュー」例外を除いて、これまで扱ってきた拡張関数は単純で、返すだけのものでした。しかし、ほとんどの関数には、通常、いくつかのパラメーターを渡して期待する目的が 1 つだけあるわけではありません。値に基づいて値を受け取り、その他の追加の処理に役立つ応答を受け取ります。
zend_parse_parameters() の自動型変換
前の章で見た戻り値と同様に、パラメータの値も zval 参照への間接的なアクセスを中心に展開します。これらの zval* の値を取得する最も簡単な方法は、zend_parse_parameters を使用することです。 () 関数。
zend_parse_parameters() の呼び出しは、ほとんどの場合、ZEND_NUM_ARGS() マクロで始まり、その後に普遍的な TSRMLS_CC が続きます。その名前から推測できるように、ZEND_NUM_ARGS() の内部動作により、実際のパラメータ数が返されます。 zend_parse_parameters() メソッドでは、おそらく値を直接知る必要はないので、とりあえず
を渡してください。zend_parse_parameters() の次のパラメータはフォーマット文字列パラメータです。これは、Zend エンジンでサポートされる基本的な型記述文字で構成される文字シーケンスであり、受け入れられる関数パラメータを記述するために使用されます。次の表は基本的な型です。文字:
文字を入力してください |
ユーザー空間のデータ型 |
b |
ブール値 |
l |
整数 |
d |
浮動小数点 |
の |
文字列 |
r |
リソース |
a |
配列 |
お |
オブジェクト インスタンス |
お |
指定された型のオブジェクト インスタンス |
z |
非特定の zval |
Z |
非特定の zval を間接参照 |
zend_parse_parameters() の残りのパラメータは、フォーマット文字列で指定された型の説明によって異なります。たとえば、long データ型は次のようにデコードされます。
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; }
通常、integer と long の記憶域スペースは同じですが、まったく同じではありません。int 型データを long* パラメーターに逆参照しようとすると、特に 64 ではエラーが発生しやすくなります。 -bit プラットフォームでは、以下の表にリストされているデータ型を厳密に使用してください。
タイプ |
C言語での対応するデータ型 |
b |
zend_bool |
l |
長い |
d |
ダブル |
の |
char *, int |
r |
zval * |
a |
zval * |
お |
zval * |
お |
zval *、zend_class_entry * |
z |
zval * |
Z |
zval * |
注意, 所有其他的复杂类型实际上都解析为简单的zval. 这样做的原因和不使用RETURN_*()宏返回复杂数据类型一样, 都是受限于无法真正的模拟C空间中的这些结构. zend_parse_parameters()能为你的函数所做的, 是确保你接收到的zval *是正确的类型. 如果需要, 它甚至会执行隐式的类型转换, 比如将数组转换为stdClass的对象.
s和O类型需要单独说明, 因为它们一次调用需要两个参数. 在第10章"php4对象"和第11章"php5对象"中你将更进一部的了解O. 对于s这个类型, 我们对第5章"你的第一个扩展"的sample_hello_world()函数进行一次扩展, 让它可以跟指定的人名打招呼.
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"); }
zend_parse_parameters()函数可能由于函数传递的参数太少不能满足格式串, 或者因为其中某个参数不能转换为请求的类型而失败. 这种情况下, 它将自动的输出错误消息, 因此你的扩展不需要这样做.
要请求超过1个参数, 就需要扩充格式串, 包括其他字符, 并将zend_parse_parameters()调用的后面其他参数压栈. 参数和它们在用户空间函数定义的行为一致, 从左向右解析.
function sample_hello_world($name, $greeting) { echo "Hello $greeting $name!\n"; } sample_hello_world('John Smith', 'Mr.'); Or: PHP_FUNCTION(sample_hello_world) { char *name; int name_len; char *greeting; int greeting_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &name, &name_len, &greeting, &greeting_len) == FAILURE) { RETURN_NULL(); } php_printf("Hello "); PHPWRITE(greeting, greeting_len); php_printf(" "); PHPWRITE(name, name_len); php_printf("!\n"); }
除了基础类型, 还有3个元字符用于修改参数处理方式. 如下表所示:
类型修改符 |
含义 |
| |
接下来是可选参数了.当指定它时,所有之前的参数都被认为是必须的,所有后续的参数都被认为是可选的. |
! |
! の前の修飾子に対応するパラメータが NULL の場合、 によって提供される内部変数は実数の に設定されます。 NULLポインタ. |
/ |
/ の前の修飾子に対応するパラメーターはコピーオンライト として指定されており、 は自動的に新しい zval(is_ref = 0、refcount = 1) |