读书人

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

发布时间: 2013-03-06 16:20:31 作者: rapoo

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

全部翻译内容pdf文档下载地址: http://download.csdn.net/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项目中, 同时保留一份独立版本.


原书名: <Extending and Embedding PHP>

原作者: Sara Golemon

译者: goosman.lei(雷果国)

译者Email: lgg860911@yahoo.com.cn

译者Blog: http://blog.csdn.net/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数据类型如下解出:

类型

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()函数进行一次扩展, 让它可以跟指定的人名打招呼.

类型修改符

含义

|

接下来是可选参数了.当指定它时,所有之前的参数都被认为是必须的,所有后续的参数都被认为是可选的.

!

!之前的一个修饰符对应的参数如果是NULL,提供的内部变量将被设置为真实的NULL指针.

/

/之前的一个修饰符对应的参数指定为写时拷贝,它将自动的隔离到新的zval(is_ref = 0, refcount = 1)


可选参数

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

static    ZEND_BEGIN_ARG_INFO(php_sample_class_arginfo, 0)        ZEND_ARG_OBJECT_INFO(1, "obj", "stdClass", 0)    ZEND_END_ARG_INFO()

要注意到这里的第一个参数(by_ref)被设置为1. 通常来说这个参数对对象来说并不是很重要, 因为ZE2中所有的对象默认都是引用方式的, 对它们的拷贝必须显式的通过clone来实现. 在函数调用内部强制clone可以做到, 但是它和强制引用完全不同.

因为当设置了zend.ze1_compatiblity_mode标记时, 你可能关心ZEND_ARG_OBJECT_INFO一行的by_ref设置. 这种特殊情况下, 对象可能仍然传递的是一个拷贝而不是引用. 因为你在处理对象的时候, 可能需要的是一个真正的引用, 因此设置这个标记你就不用担心这一方面的影响.

不要忘记了数组和对象的参数信息宏中有一个allow_null选项. 关于允许NULL的细节请参考前一章的编译期引用传值一节.

当然, 使用使用参数信息进行类型暗示只在ZE2中支持, 如果你想让你看的扩展兼容php4, 需要使用zend_get_parameters(), 这样就只能将类型验证放到函数内部, 手动的通过测试Z_TYPE_P(value)或使用第2章看到的convert_to_type()方法进行自动类型转换来完成.

小结

现在你的手头可能已经有点脏乱了, 和用户空间通信的功能代码通过简单的输入/输出函数实现. 已经比较深入的了解了zval的引用计数系统, 并学习了控制变量传递到你的内部函数方法和时机.

下一章将开始学习数组数据类型, 并了解用户空间的数组表示怎样映射到内部的HashTable实现. 此外还将看到一大批可选的Zend以及php api函数, 它们用于操纵这些复杂的结构体.


目录上一章: 返回值
下一章: 在数组和哈希表上工作

读书人网 >PHP

热点推荐