• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

[通译][php扩展和嵌入式]第7章-接受参数

php 搞代码 3年前 (2022-01-24) 51次浏览 已收录 0个评论

[翻译][php扩展和嵌入式]第7章-接受参数

全部翻译内容pdf文档下载地址: http://download.gaodaima.com/detail/lgg201/5107012

本书目前在github上由laruence(http://www.laruence.com)和walu(http://www.walu.cc)两位大牛组织翻译. 该翻译项目地址为: https://github.com/walu/phpbook

本书在github上的地址: https://github.com/goosman-lei/php-eae

未来本书将可能部分合并到phpbook项目中, 同时保留一份独立版本.

原书名:

原作者: Sara Golemon

译者: goosman.lei(雷果国)

译者Email: [email protected]

译者Blog: http://blog.gaodaima.com/lgg201

权利声明

此译本在不获利的情况下, 可以无限制自由传播.

除了几个”预览”的例外, 你迄今处理的扩展函数都很简单, 只有返回. 然而, 多数函数并非只有一个目的. 你通常会传递一些参数, 并希望接收到基于值和其他附加处理的有用的响应.

zend_parse_parameters()的自动类型转换

和上一章你看到的返回值一样, 参数的值也是围绕着对zval引用的间访展开的. 获取这些zval*的值最简单的方法就是使用zend_parse_parameters()函数.

调用zend_parse_parameters()几乎总是以ZEND_NUM_ARGS()宏接着是无所不在的TSRMLS_CC. ZEND_NUM_ARGS()从名字上可以猜到, 它返回int型的实际传递的参数个数. 由于zend_parse_parameters()内部工作的方法, 你可能不需要直接了解这个值, 因此现在只需要传递它.

zend_parse_parameters()的下一个参数是格式串参数, 它是由Zend引擎支持的基础类型描述字符组成的字符序列, 用来描述要接受的函数参数. 下表是基础的类型字符:

类型字符

用户空间数据类型

b

Boolean

l

Integer

d

Floating point

s

String

r

Resource

a

Array

o

Object instance

O

Object instance of a specified type

z

Non-specific zval

Z

Dereferenced non-specific zval

zend_parse_parameters()剩下的参数依赖于你的格式串中所指定的类型描述. 对于简单类型, 直接解引用为C语言的基础类型. 例如, 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位平台上更加容易出错. 因此, 请严格使用下表中列出的数据类型.

类型

C语言中的对应数据类型

b

zend_bool

l

long

d

double

s

char *, int

r

zval *

a

zval *

o

zval *

O

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_6来源gaodaimacom搞#^代%!码网搞gaodaima代码ref = 0, refcount = 1)

可选参数

我们再来看一看修订版的sample_hello_world()示例, 下一步是增加一个可选的$greeting参数:

function sample_hello_world($name, $greeting='Mr./Ms.') {    echo "Hello $greeting $name!\n";}

sample_hello_world()现在可以只用$name参数调用, 也可以同时使用两个参数调用.

sample_hello_world('Ginger Rogers','Ms.');sample_hello_world('Fred Astaire');

当不传递第二个参数时, 使用默认值. 在C语言实现中, 可选参数也是以类似的方式指定.

要完成这个功能, 我们需要使用zend_parse_parameters()格式串中的管道符(|). 管道符左侧的参数从调用栈解析, 所有管道符右边的参数如果在调用栈中没有提供, 则不会被修改(zend_parse_parameters()格式串后面对应的参数). 例如:


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:[通译][php扩展和嵌入式]第7章-接受参数
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址