PHP扩展开发基础(一)

标签: 扩展开发, php

0x01 关于PHP扩展开发

PHP之所以那么成功,个人认为很重要的一个原因就是它拥有大量可用扩展。无论你有什么需求,想要实现什么功能,基本上都能在PHP的发行包中找。包括加密、数据库、图形图像、XML、压缩解压等。

PHP的扩展可以在pecl.php.net/package/ 或者 github.com

学习PHP扩展开发之前需要以下准备工作。

找个开发扩展的理由
掌握C语言开发
熟悉Linux下开发
看完本系列文章

通常来说开发PHP扩展的理由要么是要为了支持某种PHP尚未支持的服务,要么是为了优化现有业务或者加密部分重要业务,亦或是为了深入学(Install)习(B)PHP内核。

本系列文章均在Linux下开发,不要问Win,再问自杀。其次,本系列文章不会过于深入PHP扩展开发,如果有需要,建议阅读学习亚一程的相关代码(亚一程的github)。

准备开发之前,请先clone一份php的源代码。PHP源码在UNIX系统下有个ext_skel脚本用来构建基础扩展结构,所有扩展均以此为基础。

最后,god bless you!

0x02 开始PHP扩展开发之旅

首先介绍下我的环境:

PHP 5.6.8 (cli) (built: Aug 7 2015 13:03:17) (DEBUG)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies

克隆下来的PHP源码版本是5.3.9。

查看PHP源码版本:php-src$ cat main/php_version.h

我们编写一个mstring扩展,实现一个ms_concat函数,函数原型使用PHP实现如下:

<?php
function concat($str, $num) {
    $ret = '';
    while($num--) {
        $ret .= $str;
    }
    return $ret;
}
var_dump(concat('Hello',2));//HelloHello
?>

在PHP源码的ext目录执行
php-src/ext$ ./ext_skel --extname=mstring
....
To use your new extension, you will have to execute the following steps:
....

执行成功之后就会在php-src/ext目录下看到mstring文件夹,mstring扩展相关代码实现和编译、测试脚本等均在此目录。

修改mstring/config.m4文件,此文件是Linux下扩展编译脚本,dnl开头的均为注释。

dnl PHP_ARG_ENABLE(mstring, whether to enable mstring support,
dnl Make sure that the comment is aligned:
dnl [  --enable-mstring           Enable mstring support])

修改为以下代码,用来编译时支持 --enable-mstring 参数。

PHP_ARG_ENABLE(mstring, whether to enable mstring support,
[  --enable-mstring           Enable mstring support])

关于此文件详解请关注后续文章。

0x03 给扩展增加一个功能

编辑php_mstring.h文件

PHP_FUNCTION(confirm_mstring_compiled); /* For testing, remove later. */
PHP_FUNCTION(ms_concat);//新增一个函数,合并数组

编辑mstring.c文件

首先给mstring扩展增加一个函数。

const zend_function_entry mstring_functions[] = {
PHP_FE(confirm_mstring_compiled,    NULL)       /* For testing, remove later. */
PHP_FE(ms_concat,           NULL)       /* 新增一个方法   */
PHP_FE_END  /* Must be the last line in mstring_functions[] */
};

具体实现:

PHP_FUNCTION(ms_concat)
{
char *str = NULL;
int str_len, res_len;
long n;
char *res, *ptr;
    //接收函数参数
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &str, &str_len, &n) == FAILURE) {
    return;
}
//计算结果的长度
res_len = (str_len * n);
//初始化结果值的内存空间
res = (char *) emalloc(res_len + 1);
ptr = res;
while (n--) {
    memcpy(ptr, str, str_len);/* 将str复制到结果中 */
    ptr += str_len;/* 移动指针 */
}
*ptr = '\0';
RETURN_STRINGL(res, res_len, 0);
}

0x04 安装&测试扩展

/usr/local/php-5.6.8/bin/phpize
./configure --enable-mstring --with-php-config=/usr/local/php-5.6.8/bin/php-config
make
sudo make install

并加载php扩展,写个简单的php测试脚本:

<?php
var_dump(confirm_mstring_compiled('mstring'));
var_dump(ms_concat('Hello', 3));
var_dump(ms_concat(123, '2'));
var_dump(ms_concat('456', 3));
?>

执行结果

string(111) "Congratulations! You have successfully modified         ext/mstring/config.m4. Module mstring is now compiled into PHP."
string(15) "HelloHelloHello"
string(6) "123123"
string(9) "456456456"

结果符合预期,后面会再尝试写一个支持OO的扩展类。


评论已关闭