1 参数接收
前面我们讲到了php扩展开发的大体架构,本节我们介绍扩展如何接收php脚本中传入的参数。
1.1 普通参数接收
任务:写一个扩展,输出php脚本传入的参数。例如php –r “echo hello(‘param test.’);” 将要输出param test.
首先我们建立一个paramtest的扩展,建议、编译、安装、测试过程不再赘述。
首先,我们需要建立一个函数叫做hello,建立的过程和之前是一样的,也不多说。
我们具体看一下,hello函数的实现,paramtest.c中hello函数的实现如下:
PHP_FUNCTION(hello)
{
char* str_hello;
int int_hello_str_length;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s",
&str_hello,&int_hello_str_length)== FAILURE)
{
RETURN_NULL();
}
php_printf("%s", str_hello);
RETURN_TRUE;
}
我们先看一下zend_parse_parameters的函数定义:ZEND_NUM_ARGS() TSRMLS_CC其实是zend_parse_parameters的两个参数,具体可以查找这两个宏的定义,这两个宏主要是传入参数信息和保证线程安全。参数”s”其实是格式化字符串,也就是说这个参数告诉ZEND编译器,我可以接收的参数类型是什么样子的。Zend_parse_parameters的其他参数负责具体接收php脚本中函数变量的值。
请注意:我们在php脚本的函数中传入了一个参数,但是在zend_parse_parameters中却需要两个参数进行接收,给大家解释一下原因:我们在php脚本中传入的参数是字符串,对于C语言来说,PHP脚本传入字符串的长度是无法直接用函数strlen来进行获取的。原因是因为,我们在php脚本中可以传入\0,但是\0在C语言中是字符串结尾的意思。
在zend_parse_parameters中,格式化字符创(本例中是”s”)有很多,如果你想要接受多个参数的话,只要在格式化参数中加入相应的类型标示符,在参数中添加接受变量就可以了。例如,如果你的php函数需要传入两个变量,第一个变量为问候字符串,第二个参数为bool,表示是否输出,那么zend_parse_parameters函数可以这样写:zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sb", &str_hello,&len, &is_output)。
其中,格式化字符串可以列表如下:
PHP变量类型 | 代码 | C扩展变量类型 |
boolean | b | zend_bool |
long | l | long |
double | d | double |
string | s | char*, int |
resource | r | zval* |
array | a | zval* |
object | o | zval* |
zval | z | zval* |
上表中有很多zval类型,这个类型我们下一节进行单独介绍。
另外一个需要注意的地方是,我们使用php_printf在C函数中进行输出,你能想到原因吗?前面我们已经讲到php既可以作为脚本在命令行运行,也可以通过web服务器,以单进程、多进程、多线程方式运行,如果我们在web服务器中将我们的信息输出到stdout中,会导致信息无法输出或者输出错误。给大家举个例子,我们可以再apache+php环境中写一个脚本,通过浏览器访问这个脚本,如果你使用printf输出字符串,那么浏览器将无法看到你的输出信息。但是如果你使用php_printf输出的话,浏览器就能显示你输出的信息。
1.2 可选参数接收
我们已经学会了如何接收普通参数,大家都知道php中还有可选参数,那么我们改怎样接收可选参数呢?(如果你不知道php可以使用可选参数的话,建议你先温习一下php的基础知识。)
这个很简单,我们直接上代码:
PHP_FUNCTION(hello)
{
char* str_hello;
int int_hello_str_length;
zend_bool is_output =0;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s|b",&str_hello,
&int_hello_str_length,&is_output)== FAILURE)
{
RETURN_NULL();
}
if(is_output)
{
php_printf("%s", str_hello);
}
RETURN_TRUE;
}
很简单吧,如果你有可选参数,那么在格式化字符串中加入|就可以了,|后面的就是可选参数,其他的和普通变量的接收是一样的。
author iamnew<[email protected]>
QQ:947847775