php扩展传参,c写php扩展传参学习记录

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

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

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

类型指定符

对应的C类型

描述

l

long

符号整数

d

double

浮点数

s

char *, int

二进制字符串,长度

b

zend_bool

逻辑型(1或0)

r

zval *

资源(文件指针,数据库连接等)

a

zval *

联合数组

o

zval *

任何类型的对象

O

zval *

指定类型的对象。需要提供目标对象的类类型

z

zval *

无任何操作的zval

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

|它之前的参数都是必须的,之后的都是非必须的,也就是有默认值的。

!如果接收了一个PHP语言里的null变量,则直接把其转成C语言里的NULL,而不是封装成IS_NULL类型的zval。

/如果传递过来的变量与别的变量共用一个zval,而且不是引用,则进行强制分离,新的zval的is_ref__gc==0, and refcount__gc==1.

下面列出几个传参例子

传字符参数

PHP_FUNCTION(str){

char *arg = NULL,*str = NULL;

int arg_len, str_len = NULL;

/**

* s代表传递字符参数,下面函数里面的"ss"代表传的是字符型参数,两个ss代表定义了两个参数

* &arg,&str取得参数地址,&arg_len,&str_len对应参数长度

*如果传递给函数的参数数量小于zend_parse_parameters()要接收的参数数量,它便会执行失败,并返回FAILURE。

*/

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &arg, &arg_len, &str, &str_len) == FAILURE) {

return;

}

PHPWRITE(arg, arg_len);

php_printf("  ");

PHPWRITE(str, str_len);

}

传数组参数

PHP_FUNCTION(array){

zval *arr, **data;

HashTable *arr_hash;

HashPosition pointer;

int array_count;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arr) == FAILURE) {

RETURN_NULL();

}

arr_hash = Z_ARRVAL_P(arr);

array_count = zend_hash_num_elements(arr_hash);

php_printf("The array passed contains %d elements ", array_count);

for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer);

zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS;

zend_hash_move_forward_ex(arr_hash, &pointer)) {

convert_to_string_ex(data);

PHPWRITE(Z_STRVAL_PP(data), Z_STRLEN_PP(data));

php_printf(" ");

}

RETURN_TRUE;

}

定义参数默认值

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

ZEND_FUNCTION(str_1)

{

char *greeting = "Mr./Mrs.";                //定义参数默认值,如果没有传递参数,则默认输出Mr./Mrs.

int greeting_len = sizeof("Mr./Mrs.") - 1;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &greeting, &greeting_len) == FAILURE) {

RETURN_NULL();

}

RETVAL_STRING(greeting, 1);

}

可变参数(摘录)

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

PHP_FUNCTION(diy_var_dump)

{

int i, argc = ZEND_NUM_ARGS();

zval ***args;

args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);

if (ZEND_NUM_ARGS() == 0 || zend_get_parameters_array_ex(argc, args) == FAILURE)

{

efree(args);

WRONG_PARAM_COUNT;

/*

*这里,WRONG_PARAM_COUNT是一个宏定义(zend_API.h):

*ZEND_API void wrong_param_count(void);

*#define WRONG_PARAM_COUNT { wrong_param_count(); return; }

*如果参数个数错误,WRONG_PARAM_COUNT会打印出相应的错误信息。

*/

}

for (i=0; i

{

php_var_dump(args[i], 1 TSRMLS_CC);

}

efree(args);        //稀放内存

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值