本教程将实现一个阶乘扩展,编译环境为:CentOS7/PHP5.6.3,其PHP函数实现如下:
定义函数原型
我们首先在php源码的扩展目录定义一个文件名为”factorial.def”的文件,并在里面写上如下内容:
生成扩展基本代码
这时候我们就可以使用php官方为我们提供的工具ext_skel,来生成扩展的基本代码,命令如下:
其中extname表示要生成的扩展名称,proto表示函数原型的文件路径
扩展配置修改
经过上一步的代码生成,现在当前目录下应该出现了一个factorial的目录,我们进入这个目录,并编辑目录下的“config.m4”文件,将以下两行代码前的dnl删除,如下:
功能实现
接下来就是我们今天的主菜了,我们修改一下factorial.c,找到函数主体,修改为如下代码:
代码中的zend_parse_parameters是用来检验输入参数的,它的第三个参数表示的是输入参数的类型,觉的类型表示如下表所示:
| 类型指定符 | 对应的C类型 | 描述 | 
|---|---|---|
| l | long | 长整数 | 
| d | double | 浮点数 | 
| s | char *, int | 二进制字符串,长度 | 
| b | zend_bool | 逻辑型(1或0) | 
| r | zval * | 资源(文件指针,数据库连接等) | 
| a | zval * | 联合数组 | 
| o | zval * | 任何类型的对象 | 
| O | zval * | 指定类型的对象。需要提供目标对象的类类型 | 
| z | zval * | 无任何操作的zval | 
| foo | foo | foo | 
| bar | bar | bar | 
| baz | baz | baz | 
扩展函数的返回值,需要使用php预设的宏定义来返回,常见的宏定义如下表所示:
| 宏定义 | 设置返回值 | 宏返回类型和参数 | 
|---|---|---|
| RETURN_LONG(l) | RETVAL_LONG(l) | 整数 | 
| RETURN_BOOL(b) | RETVAL_BOOL(b) | 布尔数(1或0) | 
| RETURN_NULL() | RETVAL_NULL() | NULL | 
| RETURN_DOUBLE(d) | RETVAL_DOUBLE(d) | 浮点数 | 
| RETURN_STRING(s, dup) | RETVAL_STRING(s, dup) | 字符串。如果dup为1,引擎会调用estrdup()重复s,使用拷贝。如果dup为0,就使用s | 
| RETURN_STRINGL(s, l, dup) | RETVAL_STRINGL(s, l, dup) | 长度为l的字符串值。与上一个宏一样,但因为s的长度被指定,所以速度更快。 | 
| RETURN_TRUE | RETVAL_TRUE | 返回布尔值true。注意到这个宏没有括号。 | 
| RETURN_FALSE | RETVAL_FALSE | 返回布尔值false。注意到这个宏没有括号。 | 
| RETURN_RESOURCE(r) | RETVAL_RESOURCE(r) | 资源句柄。 | 
编译扩展
执行以下命令,执行扩展编译:
添加扩展
编辑php.ini,加入如下代码:
代码添加后,我们需要重启一下php-fpm.
至此,我们就将扩展添加进PHP了,这时我们可以编写一个php文件来做测试,如下: