PHP 程序员大概都知道可以用 C/C++ 来扩展 PHP. 现在网络上关于 PHP 扩展开发的资料也已经很多了, 假如你恰巧有 C/C++ 基础, 那么不妨进阶学习开发 PHP 扩展. 下面以一个简单示例 tl_toolkit 来介绍 PHP 扩展开发流程.
开发环境
1. CentOS 7.5
2. PHP 7.1 源码
开发步骤
1. 生成扩展目录
PHP 源码扩展目录 ext / 中包含生成扩展基本目录的工具 ext_skel, 使用该工具可以很方便的生成扩展基本目录.
- [root@ef40a04d7af1 ext]# ./ext_skel
- ./ext_skel --extname=module [--proto=file] [--stubs=file] [--xml[=file]]
- [--skel=dir] [--full-xml] [--no-help]
- --extname=module module is the name of your extension
- --proto=file file contains prototypes of functions to create
- --stubs=file generate only function stubs in file
- --xml generate xml documentation to be added to phpdoc-SVN
- --skel=dir path to the skeleton directory
- --full-xml generate xml documentation for a self-contained extension
- (not yet implemented)
- --no-help don't try to be nice and create comments in the code
- and helper functions to test if the module compiled
生成扩展基本目录很简单, 如下:
- [root@ef40a04d7af1 ext]# ./ext_skel --extname=tl_toolkit
- Creating directory tl_toolkit
- Creating basic files: config.m4 config.w32 .gitignore tl_toolkit.c php_tl_toolkit.h CREDITS EXPERIMENTAL tests/001.phpt tl_toolkit.PHP [done].
- To use your new extension, you will have to execute the following steps:
- 1. $ cd ..
- 2. $ vi ext/tl_toolkit/config.m4
- 3. $ ./buildconf
- 4. $ ./configure --[with|enable]-tl_toolkit
- 5. $ make
- 6. $ ./sapi/cli/PHP -f ext/tl_toolkit/tl_toolkit.PHP
- 7. $ vi ext/tl_toolkit/tl_toolkit.c
- 8. $ make
- Repeat steps 3-6 until you are satisfied with ext/tl_toolkit/config.m4 and
- step 6 confirms that your module is compiled into PHP. Then, start writing
- code and repeat the last two steps as often as necessary.
2. 实现扩展方法
2.1 修改 config.m4 文件. config.m4 文件内说明, 该文件以 dnl 为注释符.
- dnl $Id$
- dnl config.m4 for extension tl_toolkit
- dnl Comments in this file start with the string 'dnl'.
- dnl Remove where necessary. This file will not work
- dnl without editing.
- dnl If your extension references something external, use with:
- dnl PHP_ARG_WITH(tl_toolkit, for tl_toolkit support,
- dnl Make sure that the comment is aligned:
- dnl [ --with-tl_toolkit Include tl_toolkit support])
- dnl Otherwise use enable:
- PHP_ARG_ENABLE(tl_toolkit, whether to enable tl_toolkit support,
- Make sure that the comment is aligned:
- [ --enable-tl_toolkit Enable tl_toolkit support])
删除 config.m4 文件中 16 至 18 行前 dnl.
2.2 引用多个. c 源文件 (可选). 如果你的扩展, 包含多个 c 源文件, 那么在 config.m4 文件最后 PHP_NEW_ EXTENSION 函数内引用进来. tl_toolkit 扩展就增加一个 tl_string.c 文件. 那么就像如下引用进来:
PHP_NEW_EXTENSION(tl_toolkit, tl_toolkit.c tl_string.c, $ext_shared, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
2.3 修改 php_tl_toolkit.h 头文件, 在最后 #endif /* PHP_TEST_H */ 前添加 PHP_FUNCTION(tl_get_arch);
2.4 实现 tl_get_arch 方法. 这个方法的作用是获取系统位数, 返回 32 或者 64. 具体实现我们使用 phalcon 项目中的代码. 所以在 tl_string.c 中 tl_get_arch 的实现就是:
- // Check Windows
- #if _WIN32 || _WIN64
- #if _WIN64
- #define ENVIRONMENT64
- #else
- #define ENVIRONMENT32
- #endif
- #endif
- // Check GCC
- #if __GNUC__
- #if __x86_64__ || __ppc64__
- #define ENVIRONMENT64
- #else
- #define ENVIRONMENT32
- #endif
- #endif
- /*{{ tl_get_arch
- */
- PHP_FUNCTION(tl_get_arch)
- {
- #ifndef ENVIRONMENT32
- RETURN_LONG(64);
- #else
- RETURN_LONG(32);
- #endif
- }
- /* }}} */
2.5 注册 tl_get_arch 方法. 在 ext_skel 生成的扩展源码文件 tl_toolkit.c 中, 找到 zend_function_entry 添加 PHP_FE(tl_get_arch, NULL).
- /* {{{ tl_toolkit_functions[]
- *
- * Every user visible function must have an entry in tl_toolkit_functions[].
- */
- const zend_function_entry tl_toolkit_functions[] = {
- PHP_FE(tl_toolkit_info, NULL)
- PHP_FE(tl_authcode, NULL)
- PHP_FE(tl_get_arch, NULL)
- PHP_FE_END
- };
- /* }}} */
3. 添加测试用例
ext_skel 生成的扩展目录包含一个 tests 目录, 里面有一个 001.phpt 测试文件. 编译扩展时执行 make test 就会运行这些测试用例文件.*.phpt 的结构说明如下:
--TEST-- : 测试用例名
--SKIPIF-- : 跳过测试用例的条件
--INI--: 执行测试用例需要的 INI 配置
--FILE-- : 测试用例运行的 PHP 代码
--EXPECT-- : 期望输出结果
所以我为 tl_get_arch 方法添加一个测试用例如 003.phpt 下:
- --TEST--
- Test function tl_get_arch of tl_toolkit
- --SKIPIF--
- <?PHP if (!extension_loaded("tl_toolkit")) print "skip"; ?>
- --FILE--
- <?PHP
- echo tl_get_arch();
- ?>
- --EXPECT--
- 64
4. 编译安装扩展
在扩展目录执行:
- /usr/local/PHP/bin/phpize
- ./configure
- make && make install
make 成功后会提示执行 make test, 执行 make test 会输出如下结构信息:
- =====================================================================
- PHP : /usr/local/PHP-7.1.12/bin/PHP
- ---------------------------------------------------------------------
- PHP : /usr/local/PHP-7.1.12/bin/phpdbg
- ---------------------------------------------------------------------
- CWD : /root/Download/PHP-7.1.12/ext/tl_toolkit
- Extra dirs :
- VALGRIND : Not used
- =====================================================================
- TIME START 2019-03-12 22:33:19
- =====================================================================
- PASS Check for tl_toolkit presence [tests/001.phpt]
- PASS Test function tl_authcode of tl_toolkit [tests/002.phpt]
- PASS Test function tl_get_arch of tl_toolkit [tests/003.phpt]
- =====================================================================
- TIME END 2019-03-12 22:33:19
- =====================================================================
- TEST RESULT SUMMARY
- ---------------------------------------------------------------------
- Exts skipped : 0
- Exts tested : 1
- ---------------------------------------------------------------------
- Number of tests : 3 3
- Tests skipped : 0 ( 0.0%) --------
- Tests warned : 0 ( 0.0%) ( 0.0%)
- Tests failed : 0 ( 0.0%) ( 0.0%)
- Expected fail : 0 ( 0.0%) ( 0.0%)
- Tests passed : 3 (100.0%) (100.0%)
- ---------------------------------------------------------------------
- Time taken : 0 seconds
- =====================================================================
最后, 修改 PHP.INI 文件, 添加 extension=tl_toolkit.so, 并重启 PHP, 然后就可以在 PHP 代码中调用 tl_get_arch 方法了.
tl_toolkit 扩展完整的代码移步 GitHub https://github.com/One2r/tl_toolkit
相关资料
下面是我在学习 PHP 扩展开发时收集的一些资料, 都是 PHP 界大牛写的博客或书籍, 整理分享出来方便学习, 希望能帮助想学 PHP 扩展或者正在学习的人.
1. 《深入理解 PHP 内核》
2. 《PHP 扩展开发及内核应用》
3. 信海龙 php7 扩展系列博文
4. PHP Internals Book
来源: http://www.jianshu.com/p/f12d90b71776