本教程将实现一个阶乘扩展,编译环境为:CentOS7/PHP5.6.3,其PHP函数实现如下:1
2
3
4
5
6
7
8
9
10
function  factorial ($number)  {
  if ($number < 1 ) return  0 ;
  $i = 1 ;
  $result = 1 ;
  while ($i <= $number){
    $result *= $i;
    $i++;
  }
  return  $result;
}
注意:由于这个函数只用于演示,未考虑大数的阶乘,在使用大数进行阶乘时,有可能会发生整形溢出。  
定义函数原型 我们首先在php源码的扩展目录定义一个文件名为”factorial.def”的文件,并在里面写上如下内容:1
long  factorial (int  number) 
生成扩展基本代码 这时候我们就可以使用php官方为我们提供的工具ext_skel,来生成扩展的基本代码,命令如下:1
./ext_skel --extname=factorial --proto=factorial.def
其中extname表示要生成的扩展名称,proto表示函数原型的文件路径
扩展配置修改 经过上一步的代码生成,现在当前目录下应该出现了一个factorial的目录,我们进入这个目录,并编辑目录下的“config.m4”文件,将以下两行代码前的dnl删除,如下:1
2
3
PHP_ARG_ENABLE(factorial , whether to enable factorial  support,
Make sure that the comment is  aligned:
[  --enable-factorial            Enable factorial  support])
功能实现 接下来就是我们今天的主菜了,我们修改一下factorial.c,找到函数主体,修改为如下代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
PHP_FUNCTION(factorial)
{
  int  argc = ZEND_NUM_ARGS();
  long  number;
  if  (zend_parse_parameters(argc TSRMLS_CC, "l" , &number) == FAILURE)
  	return ;
  if (number < 1 )  RETURN_LONG(0 );
  long  i = 1 ;
  long  result = 1 ;
  while (i <= number){
    result *= i;
  	i++;
  }
  RETURN_LONG(result);
}
代码中的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) 
资源句柄。 
 
 
编译扩展 执行以下命令,执行扩展编译:1
2
3
/usr/local/php/bin/phpzie
./configure
make && make install
添加扩展 编辑php.ini,加入如下代码:
代码添加后,我们需要重启一下php-fpm. 至此,我们就将扩展添加进PHP了,这时我们可以编写一个php文件来做测试,如下: