首页 > PHP > php扩展开发之传参

php扩展开发之传参

2015年8月9日 发表评论 阅读评论

最近跟着服务器组同学学写C++,不是想转做C++开发,只是想借此机会锻炼一下自己.php的扩展不止可以使用原生的C,同样的可以使用C++来开发扩展来扩展我们的php.不过今天我们还不会谈C++扩展php,依旧还是原生的C来扩展我们的php.上一篇,我给了一个简单的扩展开发HelloWorld的例子.除了证明我们可以用C扩展php,它对我们日常工作可能要解决的问题来说毫无作用.今天我们来看一下php扩展传参是如果实现的,我们在日常的php开发当中写函数时要传参,同样我们看系统提供的函数中也有参数,但是我们在扩展函数的声明中是没有传参相关的参数的,那么它是如何实现的哪?

Zend API提供了解析参数的函数帮我们来解决这个问题:

ZEND_API int zend_parse_parameters(int num_args TSRMLS_DC, const char *type_spec, …)

ZEND_API int zend_get_parameters(int ht, int param_count, …)

我这里列了2个函数,zend_parse_parameters和zend_get_parameters,你可以在Zend/zend_API.c中找到他们.今天我们主要了解的是zend_parse_parameters,应为这是现阶段php5扩展中开发主要的解析参数的函数,而zend_get_parameters是针对php5之前的扩展用到的.需要你需要扩展老版本的php或者兼容旧的版本,请自行google翻阅资料,我个人觉得其意义不是很大,这里就不再多加探讨了.

zend_parse_parameters有2个主要参数,还有若干可变的参数,可变参数的作用就是接受我们php脚本中传递给扩展的参数.我们先看看这2个主要参数的作用吧:

int num_args就是本函数参数的个数,const char *type_spec是一个用于格式化的字符串,类似C里面的printf,不过他们2个却是完全不一样的.

参数   代表着的类型
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   zval**类型
f   表示函数、方法名称,PHP5.1里貌似木有... ...
下面的列表给出这些参数对应C里面的那些数据类型
参数  对应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**
后面跟的参数就是用来存储格式化字符串里面所表示的php传递的参数,需要注意的是字符串类型要占用2个参数,一个用来存储字符串,一个用来存储字符串长度.例子这里就不再单独的写了,细心的读者会发现上一篇扩展开发HelloWorld已经有介绍了.
今天我们写一个引用传参的例子,当初我在这个地方也纠结了好久,具体的是我们写一个互换2个数字的函数.
首先我们先用php写一下这个函数(注释部分为脚本输出):
<?php
$x = 1;
$y = 2;
exchange_num($x,$y);
echo $x."\n".$y."\n";
function exchange_num(&$a,&$b){
$c = $a;
$a = $b;
$b = $c;
}
//2
//1
这里我们使用了&符号来使用类似的功能,那么我们用扩展如何实现类似的引用哪?
PHP_FUNCTION(king_exchange_number){
long num1,num2;
zval *arg1,*arg2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"zz", &arg1, &arg2) == FAILURE){
RETURN_NULL();
}
num1 = Z_LVAL_P(arg1);
num2 = Z_LVAL_P(arg2);
php_printf("num1:%ld,num2:%ld\n",num1,num2);
ZVAL_LONG(arg1,num2);
ZVAL_LONG(arg2,num1);
RETURN_NULL();
}
细心的朋友会发现我没有使用long类型来接受参数,而是换成zval *来接受.最初的时候我也试图利用long来接受数据,事实上我们可以用long来接受参数,我们可以读取参数里面的值,也可以改变参数的.但是我们却无法改变外部传进来参数的值,因为参数是局部变量,它在函数执行结束以后就会被释放掉,所以我们即使改变了这些用来接受参数的变量的值,其外部参数还是不会变化的.那么如果才能做到改变外部的参数哪?答案当然是指针,只有我们传递来的是一个指针的时候,我们才可以改变外部的参数值.但是我们回顾上面格式化字符串对照表里面,没有指针,但是注意看z是对应任意类型的,所以我们这里使用z.
在你当前的zend_function_entry数组中加入(以后的例子中会省略掉这一部分,读者自行添加即可)
PHP_FE(king_exchange_number,NULL)
然后保存重新编译扩展.然后我们在用我们写的扩展使用上面的功能(注释部分为脚本的输出结果).
<?php
$num1 = 11;
$num2 = 89;
king_exchange_number($num1,$num2);
echo "\$num1:$num1\n";
echo "\$num2:$num2\n";
//$num1:89
//$num2:11
到此相信你对php扩展传参也有个大致的了解了.文中的扩展在php-5.10中运行正常,如有疑问可以留言.
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.
您必须在 登录 后才能发布评论.