发布于 1970-01-01 08:00
  • 1 个回答
    • 思路差不多的.PHP7源代码ext下的扩展的代码可以说都是标准范例.
      还有,鸟哥的Yaf/Yar/Yac等等,峰哥的Swoole都已经支持PHP7了,
      这些第三方扩展可以在 pecl.php.net 上找到.

      http://www.laruence.com/2011/09/13/2139.html
      入门: http://www.walu.cc/phpbook/
      案例: php-src/ext
      PECL开发邮件组: http://news.php.net/php.pecl.dev
      尽量编写一些phpt测试用例,php-src/tests下有很多参考.
      测试时用--enable-debug编译PHP,要做到执行你的扩展逻辑,不输出任何错误信息.
      用valgrind检测内存泄露.

      Swoole作者峰哥教你怎么构建PHP扩展(视频教程):
      http://wiki.swoole.com/wiki/page/238.html
      http://php.net/manual/zh/internals2.buildsys.php
      php-src/ext/ext_skel脚本用于生成PECL扩展源码骨架.

      PECL扩展开发步骤(假设你的扩展名叫codenc):
      cd php-src/ext
      ./ext_skel --extname=codenc
      Creating directory codenc
      Creating basic files:
      config.m4 扩展的configure配置文件(Linux)
      config.w32 扩展的configure配置文件(Windows)
      codenc.c 扩展主文件
      php_codenc.h 扩展头文件(定义扩展版本号PHP_CODENC_VERSION)
      codenc.php 显示扩展提供的函数
      tests/001.phpt 测试脚本
      CREDITS 鸣谢
      EXPERIMENTAL 实验
      .svnignore SVN忽略目录或文件.deps,.lo,.la

      [done].
      To use your new extension, you will have to execute the following steps:
      1.  $ cd ..
      2.  $ vi ext/codenc/config.m4
      3.  $ ./buildconf
      4.  $ ./configure --[with|enable]-codenc
      5.  $ make
      6.  $ ./sapi/cli/php -f ext/codenc/codenc.php
      7.  $ vi ext/codenc/codenc.c
      8.  $ make
      Repeat steps 3-6 until you are satisfied with ext/codenc/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.
      

      编辑config.m4:
      把:

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

      改成:

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

      其中dnl是注释符号.
      编辑config.w32:
      把:

      // ARG_ENABLE("codenc", "enable codenc support", "no");
      

      改为:

      ARG_ENABLE("codenc", "enable codenc support", "no");
      

      执行phpize根据config.m4生成扩展的configure脚本:

      /png/php/5.4.39NTS/bin/phpize
      Configuring for:
      PHP Api Version:         20100412
      Zend Module Api No:      20100525
      Zend Extension Api No:   220100525
      

      执行configure生成Makefile用于make编译:

      ./configure --with-php-config=/png/php/5.4.39NTS/bin/php-config
      checking ...
      config.status: creating config.h
      

      执行 make && make install 编译并安装扩展:

      Libraries have been installed in: /home/eechen/png_stack/php-5.4.39/ext/codenc/modules
      Installing shared extensions: /png/php/5.4.39NTS/lib/php/extensions/no-debug-non-zts-20100525/
      

      在 php.ini 加载扩展:

      extension=codenc.so
      

      测试:

      php -r 'echo confirm_codenc_compiled("codenc")."\n";'
      

      输出:
      Congratulations! You have successfully modified ext/codenc/config.m4.
      Module codenc is now compiled into PHP.
      打开 php_codenc.h 和 codenc.c 可见其自动生成了一个用于测试的函数 confirm_codenc_compiled

      php_codenc.h(声明):
      PHP_FUNCTION(confirm_codenc_compiled);    /* For testing, remove later. */
      
      codenc.c(注册跟实现):
      const zend_function_entry codenc_functions[] = {
          PHP_FE(confirm_codenc_compiled,    NULL)        /* For testing, remove later. */
          PHP_FE_END    /* Must be the last line in codenc_functions[] */
      };
      PHP_FUNCTION(confirm_codenc_compiled) {}
      

      修改代码后,重新执行 make && make install 编译安装.

      PECL模块加载卸载时执行的函数:
      MINIT: Module Init (Beast和Blenc模块解密时会在这里重写zend_compile_file.缓存模块APC和Opcache也是在此起作用)
      RINIT: Request Init (Session模块和VLD扩展都在这里起作用,VLD能够兼容Beast和Opcache)
      RSHUTDOWN: Request Shutdown (register_shutdown_function,FPM提供的fastcgi_finish_request在这里起作用)
      MSHUTDOWN: Module Shutdown (Beast和Blenc模块在这里重置函数 zend_compile_file = old_compile_file)

      PHP_MINIT_FUNCTION(MyModule);
      当模块被Zend Engine加载后,例如Apache或者PHP-FPM启动,加载了PHP模块,
      Zend Engine会对每一个扩展模块调用此函数(如果有的话),可以在该函数里进行一些初始化操作.

      PHP_MSHUTDOWN_FUNCTION(MyModule);
      当Zend Engine收到shutdown信号后,例如Apache卸载PHP模块,
      Zend Engine对每一个模块调用此函数,最后关闭自己的核心子系统.

      PHP_RINIT_FUNCTION(MyModule);
      对于每一个使用该模块的PHP脚本请求前,都执行该函数(如果有的话).
      最好的例子:Session扩展模块,如果在一个PHP脚本里执行session.start(),
      Session模块的PHP_RINIT_FUNCTION()将被调用.

      PHP_RSHUTDOWN_FUNCTION(MyModule);
      与PHP_RINIT_FUNCTION()相反,该函数是在一个PHP脚本执行完毕后执行,
      比如PHP-FPM提供的函数fastcgi_finish_request.

      2022-12-01 02:48 回答
    撰写答案
    今天,你开发时遇到什么问题呢?
    立即提问
    PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有