内容简介:[ PHP 内核与扩展开发系列] 函数的参数:arginfo 与类型绑定
在前面的章节中我们已经介绍过 arginfo
了,下面我们看一下如何通过其实现类型绑定,但这个特性只能在 Zend Engine 2 也就是 PHP 5 中使用。让我们再回顾一下 arginfo
的结构。每一个 arginfo
结构的声明都是通过 ZEND_BEGIN_ARG_INFO()
或者 ZEND_BEGIN_ARG_INFO_EX()
宏函数开始的,然后紧跟着几行 ZEND_ARG_*INFO()
宏函数,最终以 ZEND_END_ARG_INFO()
宏函数结束。每个宏的基本作用我们可以在第6章的最后一节看到。如果我们想重写一下 PHP 语言中的 count()
函数,可以这么做:
ZEND_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_parse_parameters()
本身可以保证传递过来的参数是一个数组。但是如果我们通过 zend_get_parameter()
函数来接收参数的话就没这么幸运了,需要我们自己进行类型校对。如果想让内核自动完成类型校对,便需要 arginfo
上场了:
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) ...
这样我们便把类型校对的工作交给了 Zend Engine,是不是有种如释重负的感觉!同时你还给参数起了个名字,这样,对于使用你的API的开发人员而言,生成的错误信息将更加有意义。我们同样可以对参数中的对象进行校验,限制其是继承自某个类或者实现了某个接口等等。
ZEND_BEGIN_ARG_INFO(php_sample_class_arginfo, 0) ZEND_ARG_OBJ_INFO(1, obj, stdClass, 0) ZEND_END_ARG_INFO()
需要注意的是,此时第一个参数的值是数字 1
,代表着以引用的方式传递。其实这个参数对于对象来说几乎没用,因为 Zend Engine 2 中所有的对象在当作函数参数的时候都是默认以引用的形式传递的。但是我们又必须把这个参数设置为数字 1
,除非你不想让你的扩展与 PHP 4 兼容。在 PHP 4 中,对象是传递的一个完整拷贝,而非通过引用。
对于数组和对象参数,不要忘记最后的允许为 NULL 的参数。更多的信息请参考第6章最后一节的有关叙述。
通过 arginfo
的方式来实现类型绑定的功能只对 Zend Engine 2 有效,也就是 PHP 5+。如果你想在PHP 4 上实现相应的功能,那需要用 zend_get_parameters()
函数来接收参数,然后通过 Z_TYPE_P()
宏函数来检测参数的类型或者通过 convert_to_type()
函数进行类型转换。
现在我们已经可以编写一个更真实的函数了,既可以接收用户传递过来的参数,也可以返回数据给调用者。为了写出高质量的代码,还需要我们多花点心思在 zval 的写时复制等特殊机制上,否则便会在接收参数和返回数据时留下一些 bug。后续的章节里,让我们去看一下 PHP 语言里强大的数组类型是如何在内核中实现的,去探究内核中的 HashTable 结构,从而能编写出更强大的 PHP 扩展。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Golang Echo数据绑定中time.Time类型绑定失败
- 如何在Symfony的表单中添加一个未绑定字段,否则绑定到一个实体?
- js双向绑定
- 延迟静态绑定——static
- 绑定自定义事件
- angular组件双向绑定
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。