c写php扩展传参学习记录

最简单的获取函数调用者传递过来的参数便是使用zend_parse_parameters()函数。

zend_parse_parameters()函数的前几个参数我们直接用内核里宏来生成便可以了,形式为:ZEND_NUM_ARGS() TSRMLS_CC,注意两者之间有个空格,但是没有逗号。从名字可以看出,ZEND_NUM_ARGS()代表这参数的个数。

紧接着需要传递个zend_parse_parameters()函数的参数是一个用于格式化的字符串,就像printf的第一个参数一样。下面表示了最常用的几个符号。

类型指定符对应的C类型描述
llong符号整数
ddouble浮点数
schar *, int二进制字符串,长度
bzend_bool逻辑型(1或0)
rzval *资源(文件指针,数据库连接等)
azval *联合数组
ozval *任何类型的对象
Ozval *指定类型的对象。需要提供目标对象的类类型
zzval *无任何操作的zval

除了上面定义的参数,还有其它的三个参数来增强我们接受参数的能力,如下:

<span class="sh_symbol">|</span>		它之前的参数都是必须的,之后的都是非必须的,也就是有默认值的。
<span class="sh_symbol">!</span>		如果接收了一个PHP语言里的null变量,则直接把其转成C语言里的NULL,而不是封装成IS_NULL类型的zval。
<span class="sh_symbol">/</span>		如果传递过来的变量与别的变量共用一个zval,而且不是引用,则进行强制分离,新的zval的is_ref__gc<span class="sh_symbol">==</span><span class="sh_number">0</span><span class="sh_symbol">,</span> <span class="sh_usertype">and</span><span class="sh_normal"> </span>refcount__gc<span class="sh_symbol">==</span><span class="sh_number">1</span><span class="sh_symbol">.</span>


下面列出几个传参例子

传字符参数

[plain]  view plain copy
  1. PHP_FUNCTION(str){  
  2.     char *arg = NULL,*str = NULL;  
  3.     int arg_len, str_len = NULL;  
  4.   
  5.     /**  
  6.      * s代表传递字符参数,下面函数里面的"ss"代表传的是字符型参数,两个ss代表定义了两个参数  
  7.      * &arg,&str取得参数地址,&arg_len,&str_len对应参数长度  
  8.      *如果传递给函数的参数数量小于zend_parse_parameters()要接收的参数数量,它便会执行失败,并返回FAILURE。  
  9.      */  
  10.     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &arg, &arg_len, &str, &str_len) == FAILURE) {  
  11.         return;  
  12.     }  
  13.   
  14.     PHPWRITE(arg, arg_len);  
  15.     php_printf("  ");  
  16.     PHPWRITE(str, str_len);  
  17. }   

传数组参数
[plain]  view plain copy
  1. PHP_FUNCTION(array){  
  2.     zval *arr, **data;  
  3.     HashTable *arr_hash;  
  4.     HashPosition pointer;  
  5.     int array_count;  
  6.   
  7.     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {  
  8.         RETURN_NULL();  
  9.     }  
  10.   
  11.     arr_hash = Z_ARRVAL_P(arr);  
  12.     array_count = zend_hash_num_elements(arr_hash);  
  13.   
  14.     php_printf("The array passed contains %d elements ", array_count);  
  15.   
  16.     for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);  
  17.         zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;  
  18.         zend_hash_move_forward_ex(arr_hash, &pointer)) {  
  19.         convert_to_string_ex(data);  
  20.         PHPWRITE(Z_STRVAL_PP(data), Z_STRLEN_PP(data));  
  21.         php_printf(" ");  
  22.     }  
  23.     RETURN_TRUE;  
  24. }   

定义参数默认值

借助zend_parse_parameters中的(|)参数,这个参数之前的参数被认为是必须的,之后的便认为是非必须的了,如果没有传递,则不会去修改载体。

[plain]  view plain copy
  1. ZEND_FUNCTION(str_1)  
  2. {  
  3.     char *greeting = "Mr./Mrs.";                //定义参数默认值,如果没有传递参数,则默认输出Mr./Mrs.  
  4.     int greeting_len = sizeof("Mr./Mrs.") - 1;  
  5.   
  6.     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &greeting, &greeting_len) == FAILURE) {  
  7.         RETURN_NULL();  
  8.     }  
  9.   
  10.     RETVAL_STRING(greeting, 1);  
  11. }  

可变参数(摘录)

有两种其它的zend_get_parameter_**函数,专门用来解决参数很多或者无法提前知道参数数目的问题。想一下php语言中var_dump()函数的用法,我们可以向其传递任意数量的参数,它在内核中的实现其实是这样的:

[plain]  view plain copy
  1. PHP_FUNCTION(diy_var_dump)  
  2. {  
  3.     int i, argc = ZEND_NUM_ARGS();  
  4.     zval ***args;  
  5.   
  6.     args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);  
  7.     if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE)  
  8.     {  
  9.         efree(args);  
  10.         WRONG_PARAM_COUNT;  
  11.         /*  
  12.          *这里,WRONG_PARAM_COUNT是一个宏定义(zend_API.h):  
  13.          *ZEND_API void wrong_param_count(void);  
  14.          *#define WRONG_PARAM_COUNT { wrong_param_count(); return; }  
  15.          *如果参数个数错误,WRONG_PARAM_COUNT会打印出相应的错误信息。  
  16.          */  
  17.     }  
  18.     for (i=0; i<argc; i++)  
  19.     {  
  20.         php_var_dump(args[i], 1 TSRMLS_CC);  
  21.     }  
  22.     efree(args);        //稀放内存  
  23. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值