简介
与用户空间的代码不同,内部函数的参数实际上并不是在函数头部声明的,而是将参数列表的地址传入每个函数—不论是否传入了参数—而且,函数可以让Zend 引擎将它们转化为便于使用的东西。
通过定义 hello_greeteme() 展示输出
同样需要在三个地方增加代码:
php_hello.h
声明新的函数:
PHP_FUNCTION(hello_greetme);
hello.c
声明新的使用:
PHP_FE(hello_greetme,NULL);
及添加:
PHP_FUNCTION(hello_greetme)
{
char *name;
int name_len;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s",&name,&name_len) == FALLURE)
{
RETURN_NULL();
}
php_printf("hello %s\n",name);
RETURN_TRUE;
}
上述说明:
大多数zend_parse_parameters()块看起来总是一样的。ZEND_NUM_ARGS() 告诉Zend引擎要取得的参数的信息,TSRMLS_CC用来确保线程安全,返回值将被检查是SUCCESS 还是 FALLURE。 通常情况下,zend_parse_parameters()将返回SUCCESS;然而,如果传入参数有问题,Zend会自动输出一条错误信息并优雅地将控制权还给调用脚本。
本例指定s表明此函数期望只传入一个参数,而且该参数应该被转为string数据类型并装入通过地址传入 char* 变量(也就是通过 name);
注意,还有一个int 变量通过地址被传入 zend_parse_parameters().这使Zend引擎提供字符串的字节长度,如此二进制安全的函数不再需要依赖strlen(name)确定字符串的长度。实际上使用strlen(name)甚至得不到正确的结果,因为name可能在字符串结束之前包含一个或多个NULL字符。
一旦你的函数确切地得到了name参数,接下来要做的就是把它作为正式问候语的一部分输出。注意,用的是php_printf()而不是更熟悉的printf().使用这个函数有重要的理由的。首先,它允许字符串通过PHP的缓冲机制的处理,该机制除了可以缓冲数据,还可以执行额外的处理,比如gzip压缩。其次,虽然stdout是极佳的输出目标,使用CLI或CGI时,多数 SAPI期望通过特定的pipe或 socket 传来输出。所以,试图只是通过printf()写入 stdout可能导致数据丢失、次序颠倒或者被破坏,因为她绕过预处理。
最后,函数通过返回TRUE 将控制器还给调用程序。你可以没有显示地返回值(默认是NULL)而是让控制到达你的函数的结尾,但这是坏习惯。函数如果不传回任何有意义的结果,应该返回TRUE以说明“完成任务,一切正常”。