天天看点

PHP扩展开发-05-参数接收1      参数接收

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