在我们的test框架的目录下,我们先关注两个自动生成的重要的文件php_test.h,和test.c
php_test.h 是一个头文件,用来定义常量,我们新加的一些方法等。
test.c 具体实现各函数的功能。
那么我们如果为test扩展添加一个函数,函数名叫test_hello,并且输出“Hello, World!”字符串。如何做到?
第一步:声明函数
首先我们要告诉php内核,我们要新增一个函数,即在头文件中声明这个函数。那么如何声明呢?php的zend引擎为我们提供了一个宏:
PHP_FUNCTION(function_name);
这个function_name就是我们要声明的函数的名称。于是我们在test_hello.h中添加一行:
PHP_FUNCTION(test_hello);
同时我们可以,看到test_hello.h中也定义了另外一个函数,confirm_test_compiled.如下:
PHP_FUNCTION(confirm_test_compiled);
这个是一个测试方法,直接删除掉。
第二步:函数与test模块绑定
PHP内核知道我们要新增一个函数。但是,这个函数,是属于哪个模式呢?PHP并不知道。有人说,我代码都写在test模块里面了,它能不知道。很不幸地告诉你,他真不知道,如果有意见可以找PHP官方理论吧。不过,我们可以在test.c文件中找到这么几行代码。
const zend_function_entry test_functions[] = {
PHP_FE(confirm_test_compiled, NULL)
{NULL, NULL, NULL}
};
这是什么意思呢?test_functions是一个数组,它存储的是test模块下的所有函数的定义。
其中PHP_FE()也是一个宏,第一个参数表示函数名,第二个参数是函数参数的指针。我们也看到里面已经定义了一个测试方法confirm_test_compiled. 我们把它删掉,换成我们自己的函数名。
const zend_function_entry test_functions[] = {
PHP_FE(test_hello, NULL)
{NULL, NULL, NULL}
};
第三步:实现函数功能
函数定义并且与test模块绑定后,我们就要具体实现test_hello这个函数了。
在test.c文件中,我们可以看到,测试方法confirm_test_compiled函数的实现如下:
PHP_FUNCTION(confirm_test_compiled)
{
char *arg = NULL;
int arg_len, len;
char *strg;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
return;
}
len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "test", arg);
RETURN_STRINGL(strg, len, 0);
}
先不要管它什么意思。这是个测试函数,直接删除。再加上我们自己的新函数。
PHP_FUNCTION(test_hello)
{
php_printf("Hello, World!\n");
}
php_printf()是php内核内置的一个函数。和c里的printf类似。这样我们的一个扩展就完成了。
第四步:编译安装
完成修改保存后。和上一节一样,我们在test模式的目录下同样运行make install编译安装扩展。然后将扩展拷贝到php的extensions目录下。(以后每回修改完成后都要执行此操作,可以自己写一个小脚本来实现,修改完成后运行这个脚本就可以了。以后编译安装步骤就不再描述了)至此,一个带有test_hello()方法的test扩展就完成了。是不是很简单呢?