php扩展开发详细笔记

作者:袖梨 2022-06-24

php内核编写的扩展有两个工作方式

(1). 编译为动态共享对象/可装载模块,也就是常见的 .so扩展,这种扩展可以在php的配置文件中方便的开启或者关闭

(2). 静态编译到php中,使用静态编译方法比较容易上手本文介绍方式

第一种方式:

编写或者下载扩展包

phpize

./configure

make

make install

配置php.ini中的.so文件

第二种方式:

第一步:编译安装php

1. ./configure –prefix=/opt/php56/ –enable-debug –enable-maintainer-zts

2. make

3. make install

4. make clean

这样一个新的php安装在了/opt/php56目录下

php.ini目录:/opt/php56/lib/php.ini

第二步:扩展准备工作

1. PHP在源码中提供了一个扩展骨架构造脚本: ext_skel,脚本放在/usr/local/php-5.6.25/ext目录下。它的使用方式如下:

./ext_skel –extname=mfs –proto=mfs.def

解释一下,–extname明显就是我们要创建的扩展的名称,–proto的proto是prototype的缩写,也就是扩展对外提供的函数原型,可以在这个文件中添加要导出的函数签名,每个函数做一行,这样ext_skel脚本可以自动创建它们的骨架代码。

2. 举个例子,字符串复制函数:

string self_concat(string str, int n)

把这一行保存为mfs.def文件,放在ext文件夹下。

第三步:基本骨架

1. 执行 第二步中的ext_skel命令

此时,/usr/local/php-5.6.25/ext目录下会生成mfs文件夹,并生成一些代码文件和配置文���,php扩展配置文件是/usr/local/php-5.6.25/ext/mfs/config.m4

我们需要打开16行和18行代码的注释,如图:

这样就可以重新生成configure文件可以使用enable-mfs静态编译扩展

第四步:重新生成configure文件,并编译安装php

php安装目录 /usr/local/php-5.6.25

1. ./buildconf –force

2../configure –enable-mfs –prefix=/opt/php56 –with-config-file-path=/opt/php56/lib/php.ini

3. make

4. make install

这样编译的php就带了mfs扩展,并且可以使用def文件中定义的原型函数,但是由于并没有编写函数的具体内容

可以使用/usr/local/php-5.6.25/ext/mfs/mfs.php 进行测试,如下图:

表明脚本已经编译到php了。

第五步:编写扩展函数内容

先看一下有ext_skel脚本自动生成的self_concat函数代码,在ext/mfs/mfs.c:76行

PHP_FUNCTION(self_concat){char *str = NULL;int argc = ZEND_NUM_ARGS();int str_len;long n;if (zend_parse_parameters(argc TSRMLS_CC, “sl”, &str, &str_len, &n) == FAILURE)return;php_error(E_WARNING, “self_concat: not yet implemented”);}

这些代码是一个导出函数的基本框架了。

使用PHPFUNCTION()宏来生成一个适合于Zend引擎的函数原型。其中比较重要的是 zend_parse_parameters 函数,用来获取函数传递的参数;该函数的原型是:

zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, …);

第一个参数是参数的个数,通常使用ZEND_NUM_ARGS()的返回值,TSRMLS_DC这个照写就可以了,第三个参数比较复杂是一个表示函数期望的参数类型的字符串,后面紧跟参数值的变量列表,这里有一个PHP的松散变量和动态类型推断到C语言类型的转换。

第三个参数根据一个参数类型对照表生成:

类型指定符 对应的C类型 描述
l long 符号整数
d double 浮点数
s char *, int 二进制字符串,长度
b zend_bool 逻辑型(1或0)
r zval * 资源(文件指针,数据库连接等)
a zval * 联合数组
o zval * 任何类型的对象
O zval * 指定类型的对象。需要提供目标对象的类类型
z zval * 无任何操作的zval
考虑上面代码的实例:

if (zend_parse_parameters(argc TSRMLS_CC, “sl”, &str, &str_len, &n) == FAILURE)return;

“sl”: 第一个字符s代表二进制字符串,它在后面的参数列表中对应两个值,一个 &str, 一个&strlen;第二个字符’l’(L的小写),表示整数类型参数对应 &n。

扩展中的字符串都是二进制字符串,即并不以作为字符串结束,而是使用一个str_len表示字符串长度,具体看_zval结构体。
下面的工作就是修改这个函数了。

完成第一个导出函数

将自动生成的函数更新为:

PHP_FUNCTION(self_concat)

{

char *str = NULL;

int argc = ZEND_NUM_ARGS();

int str_len;

long n;

char *result; /* Points to resulting string */

char *ptr; /* Points at the next location we want to copy to */

int result_length; /* Length of resulting string */

if (zend_parse_parameters(argc TSRMLS_CC, “sl”, &str, &str_len, &n) == FAILURE) {

return;

}

result_length = (str_len * n);

result = (char *) emalloc(result_length + 1);

ptr = result;

while (n–) {

memcpy(ptr, str, str_len);

ptr += str_len;

}

*ptr = ‘’;

RETURN_STRINGL(result, result_length, 0);

}

按���上面的方法,重新编译php,也就是第四步重新执行, 就可以在php文件中直接使用slef_concat()函数拼接字符串了。

成功输出拼接的字符串,OK!

相关文章

精彩推荐