Toggle navigation
leo's blog
PHP
JavaScript
MySQL
Linux
瞎扯
PHP7扩展开发之"传递参数"
PHP
2020-07-19 18:05:15
40
简介:
当开发PHP扩展函数时一般都需要传递参数,而参数的操作根据数据类型的不同有不同的设置操作,本文介绍PHP内置的各种数据类型的参数传递
#1、参数解析过程 1、用户自定义的函数参数在编译时会为每一个参数创建一个zend_arg_info结构,这个结构用于记录参数的名称、是否引用等相关信息。在存储函数参数与函数内部的局部变量是一致的。他们都分配在zend_execute_data上。 2、调用函数时会按照参数的顺序依次将参数的值从函数调用空间传递到被调用的函数的zend_execute_data上。 3、在内部函数中可以通过zend_parse_parameters函数将参数指定到变量上 ```c //Zend/zend_API.h ZEND_API int zend_parse_parameters(int num_args,const char *tyoe_spec,...) /* num_args函数调用时实际传递的参数 可以通过ZEND_NUM_ARGS()获取 type_spec为参数的解析规则,是一个字符串,用于标识参数的数据类型, 例如示例中的ll表示两个参数都是整型 最后一个参数表示可变参数,用于配合将参数指定到要解析的变量地址 */ ``` #2、参数类型详解 在函数zend_parse_parameters()第二个参数需要指定参数的解析规则指定数据类型,此处可以使用的值有多种,可以划分分类进行介绍 #2.1、整型(l、L) 1、l与L标识表示解析的参数类型为整型,解析到的变量类型必须是**zend_long**,不能解析到其他类型。如果传递的参数不是整形将按照类型进行转换 2、标识符后面可以使用“!” 表示该参数可以为NULL,如果容许为空则必须必须再提供一个zend_bool变量的地址 3、l与L的区别在于当传递参数不是整型缺转换为整型后大小超出范围,L将值调整为整型的最大值或者最小值 而l将报错 使用方式例如如下代码: ```c zend_long lval; zend_bool is_null; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l!", &lval, &is_null) == FAILURE) { return; } //后续逻辑代码 ``` #2.2、布尔型(b) b标识将参数解析为布尔型,解析到的变量必须为**zend_bool类型** ```c zend_bool is_null; if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &is_null) == FAILURE) { return; } ``` #2.3、浮点型(d) d标识表示将参数解析为浮点类型,解析的变量类型必须为**double类型** ```c double lval; if (zend_parse_parameters(ZEND_NUM_ARGS(), "d", &lval) == FAILURE) { return; } //后续逻辑代码 ``` #2.4、字符串(s、S、p、P) 字符串可以解析为**char *与zend_string**两种类型。 1、s表示将参数解析为char *类型,并且需要额外的提供一个size_t类型的变量指定获取字符串的长度 2、S表示将参数解析为zend_string *类型不需要额外指定变量存储字符串长度 3、p与P表示用于解析路径 ```c char *str; size_t str_len; zend_string *str2 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS", &lval,&str_len,&str2) == FAILURE) { return; } //后续逻辑代码 ``` #2.5、数组(a、A、h、H) 数组参数可以解析到**zval *与HashTable * **两种类型上 1、a与A表示将参数解析到zval* 类型上 2、h与H表示将参数解析到HashTable *类型上 ```c zval *arr; HashTable *ht; if (zend_parse_parameters(ZEND_NUM_ARGS(), "ah", &arr,&ht) == FAILURE) { return; } //后续逻辑代码 ``` #2.6、对象(o、O) 1、o与O标识表示将参数解析为对象,解析到的变量类型是zval的地址,不能解析到zend_obj上 2、O要求解析指定类或者子类的对象,类似传参时显示指定参数类型的用法 my_function(MyClass $obj) ```c zval *obj; if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; } ``` #2.7、资源 r表示解析为资源,与对象相同只能解析到zval类型上 无法直接使用zend_resource #2.8、类(C) 如果参数为一个类,那么可以使用C解析出zend_class_entry地址 此处解析到的变量可以设定为一个类,使用此方式解析时将判断找到的类与自动类的关系,只有存在父子关系才能解析 ```c zend_class_entry *ce = NULL;//初始化为NULL if (zend_parse_parameters(ZEND_NUM_ARGS(), "C", &ce) == FAILURE) { return; } ``` #2.9、回调类型callable(f) callable指函数或者方法、如果参数是函数名称的字符串、对象/类 则可以太通过f标识符解析出zend_fcall_info结构 ```c //不是地址 zend_fcall_info callable; zend_fcall_info_cache call_cache; if (zend_parse_parameters(ZEND_NUM_ARGS(), "f", &callable,&call_cache) == FAILURE) { return; } ``` 在调用函数时可以传递 func("func_name")或者func([$obj,'method'])
Top