php /path/to/php/ext/ext_skel.php 生成扩展结构

上面 ext_skel.php 是 php >= 7.3 以前的版本是 php ext_skel

  1. root@68555cf5182c:/home/www-data/php-ext/luff# tree
  2. .
  3. |-- config.m4
  4. |-- config.w32
  5. |-- include
  6. |-- luff.c
  7. |-- luff.stub.php
  8. |-- luff_arginfo.h
  9. |-- php_luff.h
  10. |-- test.php
  11. |-- tests
  12. | |-- 001.phpt
  13. | |-- 002.phpt
  14. | |-- 002.sh
  15. | |-- 003.phpt
  16. | `-- 003.sh
  17. `-- tmp-php.ini
  18. 2 directories, 13 files

config.m4

autoconf 语法规则的编译配置文件,它可以指定扩展支持的 configure 选项以及扩展需要的额外库。包含哪些源文件等

phpize 根据 config.m4 生成 configure 等文件

  1. dnl PHP_ARG_WITH(arg-name, check message, help text[, default-val[, extension-or-not]])
  2. # 注册扩展 ./configure 时试用方式
  3. # ./configure --with-luff
  4. PHP_ARG_WITH(luff, whether to enable luff support,
  5. AS_HELP_STRING([--enable-luff], [Enable luff support]))
  6. dnl PHP_ARG_ENABLE(arg-name, check message, help text[, default-val[, extension-or-not]])
  7. # 注册扩展 ./configure 时试用方式
  8. # ./configure --enable-luff
  9. PHP_ARG_ENABLE(luff, whether to enable luff support,
  10. AS_HELP_STRING([--enable-luff], [Enable luff support]))
  11. # 注册扩展
  12. if test "$PHP_LUFF" != "no"; then
  13. AC_DEFINE(HAVE_LUFF, 1, [ Have luff support ])
  14. dnl PHP_NEW_EXTENSION(extname, sources [, shared [, sapi_class [, extra-cflags [, cxx [, zend_ext]]]]])
  15. PHP_NEW_EXTENSION(luff, luff.c, $ext_shared)
  16. fi

PHP_ARG_ENABLE宏: 第一个参数表示扩展名称;第二个参数在执行 ./configure 处理到该扩展时,显示该参数的内容;第三个参数是执行 ./configure —help 的输出信息。
./configure 时会显示如下信息

  1. .
  2. .
  3. .
  4. checking whether to enable luff support
  5. .
  6. .
  7. .

./configure --help 时会显示如下信息

  1. .
  2. .
  3. .
  4. Optional Features and Packages:
  5. .
  6. .
  7. .
  8. --enable-luff Enable luff support
  9. .
  10. .
  11. .

运行 ./configure --enable-luff 命令 $PHP_LUFF 将设为 yes

PHP_NEW_EXTENSION 宏: 声明了扩展的名称、源文件列表(多个文件的时候在名称后边加空格,如果需要换行还需加上反斜杠 “\”)、次扩展是动态库还是静态库,扩展是否只能在 CLI 或 CGI 模式下运行等。

$ext_shared 参数用来声明这个扩展不是一个静态模块,而是在 php 运行时动态加载的。

创建函数

ZEND_FUNCTION

  1. # 定义 php 函数
  2. # 函数实际处理方法
  3. ZEND_FUNCTION(function_name)
  4. {
  5. php_printf("Hello PHP!");
  6. }
  7. // 把这个函数放到 zend_function_entry 数据结构里
  8. static const zend_function_entry luff_functions[] = {
  9. ZEND_FE(function_name, NULL)
  10. ZEND_FE_END
  11. };
  12. #define PHP_FUNCTION ZEND_FUNCTION
  13. #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
  14. #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS)
  15. #define ZEND_FN(name) zif_##name
  16. ZEND_FUNCTION(luff) 实际在 c 语言中是这样的
  17. void zif_luff(INTERNAL_FUNCTION_PARAMETERS)
  18. {
  19. // something
  20. }

其中,zif 是 zend internal function 的意思,zif_ 前缀是可供 PHP 语言调用的函数在 C 语言中的函数名称前缀。

zend_module_entry

  1. /* {{{ luff_module_entry */
  2. zend_module_entry luff_module_entry = {
  3. STANDARD_MODULE_HEADER,
  4. "luff", /* Extension name */
  5. luff_functions, /* zend_function_entry */
  6. PHP_MINIT(luff), /* PHP_MINIT - Module initialization */
  7. PHP_MSHUTDOWN(luff), /* PHP_MSHUTDOWN - Module shutdown */
  8. PHP_RINIT(luff), /* PHP_RINIT - Request initialization */
  9. PHP_RSHUTDOWN(luff), /* PHP_RSHUTDOWN - Request shutdown */
  10. PHP_MINFO(luff), /* PHP_MINFO - Module info */
  11. PHP_LUFF_VERSION, /* Version */
  12. STANDARD_MODULE_PROPERTIES
  13. };
  14. /* }}} */

PHP_MINFO 注册用于 php --ri luffphpinfo() 命令时输出的信息

编译

我们需要根据 config.m4 文件生成一个configure 脚本、Makefile 等文件,这一步由 phpize 来帮我们做
phpize 程序根据 config.m4 里的信息生成了许多编译 php 扩展必须的文件,比如生成 Makefile 等,这为我们省了很多的麻烦。

  1. phpize
  2. ./configure
  3. make
  4. sudo make install

加载

为了使 PHP 能够找到需要的扩展文件,我们需要把编译好的 so 文件或者 dll 文件复制到 PHP 的扩展目录下,它的地址我们可以通过 phpinfo() 输出的信息找到,也可以在 php.ini 文件里进行配置找到并配置,名称为: extension_dir 的值。默认情况下,php.ini 文件位于 /usr/local/lib/php.ini。如果找不到,我们可以通过 php -i 命令或者 <?php phpinfo(); 来查看当前加载的 php.ini 文件位置。 一旦我们设置了 extension_dir,便可以在我们的 web 文件中引用我们的扩展了,我们可以通过 dl 命令来将我们的扩展加载到内存中来。

  1. <?php
  2. dl('sample.so');
  3. var_dump(get_loaded_extensions());

上面这样每次使用扩展都需要先dl一下真是太麻烦了,其实我们有更好的办法让php运行时自动加载我们的扩展。那就是在php.ini里这样配置:

  1. extension_dir=/usr/local/lib/php/modules/
  2. extension=walu.so

这样只要我们把walu.so这个文件放置在extension_dir配置的目录下,php就会在每次启动的时候自动加载了。这样我们就可以像我们平时使用curl、Mysql扩展一样直接使用,而不用麻烦的调用dl函数了

参考