起步
最近在看 《PHP扩展开发中文教程》
的pdf版。PHP的解释器是用C语言写的,所以PHP扩展自然也是用C 语言
了。
扩展是什么
用过php的人一定也用过php扩展。php本身带有86个扩展,扩展是对php语言功能的一个延伸,php的核心由两部分组成:最底层的 Zend引擎
和 PHP内核
。ze把脚本解析成机器可读的符号,也会处理内存管理,变量作用域,程序调度。PHP内核则主要涉及主机环境(Apache,IIS,Nginx),处理与主机的通信。
动机
当php自身不满足需求的时候就可以自己去造轮子了。采用C语言开发还能一定程度上解决性能问题,而php是我最喜欢的一门编程语言,写扩展的机会自然不放过,更重要的是可以 装逼
。
新建扩展
我们要写个扩展代替以下的功能:
<?php
function hello() {
return 'hello world';
}
我的开发环境是:
系统: Ubuntu 16.04
PHP: 7.0+
gcc :4.8.4
PHP已经提供了工具用来创建扩展,并初始化代码:ext_skel
$ cd php-src/ext
$ ./ext_skel --extname=hello
工具会在当前目录生成 hello
文件夹。
修改配置文件
cd到hello,工具已经初始化了目录,打开配置文件 config.m4
:
dnl If your extension references something external, use with:
dnl PHP_ARG_WITH(hello, for hello support,
dnl Make sure that the comment is aligned:
dnl [ --with-hello Include hello support])
dnl Otherwise use enable:
dnl PHP_ARG_ENABLE(hello, whether to enable hello support,
dnl Make sure that the comment is aligned:
dnl [ --enable-hello Enable hello support])
dnl 是注释符,表示当前行是注释。这段话是说如果此扩展依赖其他扩展,去掉PHP_ARG_WITH
段的注释符;否则去掉PHP_ARG_ENABLE
段的注释符。显然我们不依赖其他扩展或lib库,所以去掉PHP_ARG_ENABLE
段的注释符:
PHP_ARG_ENABLE(hello, whether to enable hello support,
Make sure that the comment is aligned:
[ --enable-hello Enable hello support])
书写代码
工具生成的hello.c
,写上我们的实现:
PHP_FUNCTION(hello)
{
zend_string *strg;
strg = strpprintf(0, "hello world.");
RETURN_STR(strg);
}
添加到编译列表里:
const zend_function_entry hello_functions[] = {
PHP_FE(hello, NULL) /*添加这行*/
PHP_FE(confirm_hello_compiled, NULL) /* For testing, remove later. */
PHP_FE_END /* Must be the last line in hello_functions[] */
};
编译与安装
$ phpize
$ ./configure --with-php-config=/usr/local/php7/bin/php-config
$ make & make install
修改php.ini
,开启扩展,若找不到可以用phpinfo()
查看使用哪个配置文件.
extension=hello.so
写个脚本:<?php echo hello();
不出意外就能看到输出了。
额外:不使用工具写扩展
一个扩展(为避免与写过的hello冲突,采用world作为名字),至少包含3个文件: config.m4
、 php_world.h
、 world.c
。一个是phpize用来准备编译扩展的配置文件,一个是引用包含的头文件,一个是源码文件。
config.m4
PHP_ARG_ENABLE(world, whether to enable world support,
Make sure that the comment is aligned:
[ --enable-world Enable hello support])
if test "$PHP_WORLD" != "no"; then
AC_DEFINE(HAVE_WORLD,1,[ ])
PHP_NEW_EXTENSION(world, world.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
fi
php_world.h
#ifndef PHP_WORLD_H
#define PHP_WORLD_H
extern zend_module_entry hello_module_entry;
#define phpext_hello_ptr &hello_module_entry
#define PHP_WORLD_VERSION "0.1.0"
#define PHP_WORLD_EXTNAME "world"
#endif
world.c
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_world.h"
PHP_FUNCTION(world)
{
zend_string *strg;
strg = strpprintf(0, "hello world. (from world module)");
RETURN_STR(strg);
}
const zend_function_entry world_functions[] = {
PHP_FE(world, NULL)
PHP_FE_END
};
zend_module_entry world_module_entry = {
STANDARD_MODULE_HEADER,
PHP_WORLD_EXTNAME,
world_functions,
NULL,
NULL,
NULL,
NULL,
NULL,
PHP_WORLD_VERSION,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_WORLD
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
ZEND_GET_MODULE(world)
#endif
编译安装:
$ phpize
$ ./configure --with-php-config=/usr/local/php7/bin/php-config
$ make & make install
测试:
一样需要在php.ini
添加extension=world.so
不使用工具的精简的一个扩展完成。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。