Gitlib Gitlib
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)

Ravior

以梦为马,莫负韶华
首页
  • 分类
  • 标签
  • 归档
  • Golang开发实践万字总结
  • MySQL核心知识汇总
  • Redis实践总结
  • MQ实践万字总结
  • Docker数据持久化总结
  • Docker网络模式深度解读
  • 常用游戏反外挂技术总结
  • 读书笔记
  • 心情杂货
  • 行业杂谈
  • 友情链接
关于我
GitHub (opens new window)
  • PHP

    • PHP-FPM使用指南
    • PHP7新特性总结
    • PHP安全编程
    • PHP安全配置总结
    • PHP变量的值类型和引用类型
    • PHP标准规范PSR
    • PHP操作Zookeeper实践
    • PHP错误和异常处理机制详解
    • PHP的Session运行机制
    • PHP底层运行机制和原理
    • PHP反射模拟实现注解路由
    • PHP高级用法总结
    • PHP开发常用文档总结
    • PHP开发入门:Memcached扩展安装
    • PHP开发入门:PHP7安装部署
    • PHP开发入门:Redis扩展安装
    • PHP开发SPL总结
    • PHP框架常见URL模式
    • PHP扩展开发入门
      • 开发工具
        • ext_skel
        • phpize
      • 实践案例
        • 第一步:生成代码
        • 第二步,修改config.m4配置文件
        • 第三步,代码实现
        • 第四步,编译安装
        • 第五步,调用测试
      • 总结
    • PHP垃圾回收机制
    • PHP类的自动加载
    • PHP输入输出流
    • PHP微服务开发指南
    • PHP协程
    • PHP写时拷贝技术
    • PHP性能优化之Opcache
    • PHP依赖注入和控制反转
    • PHP运行模式(SAPI)
    • PHP中file_get_contents与curl区别
    • RPC的简单实现
    • Protobuf:高效数据结构化工具
    • P3P协议详解
    • Laravel之集合(Collection)总结
    • Laravel实践总结
    • Laravel之ORM总结
    • 中高级PHP实践总结
    • PHP Socket编程实战
  • Golang

  • Python

  • Javascript

  • 其他语言

  • 编程语言
  • PHP
Ravior
2018-03-06
目录

PHP扩展开发入门

PHP扩展可以在编译PHP时一起编译,也可以单独编译为共享库,共享库的像是需要将库的名称加入到php.ini配置中去,在pho_module_startup()阶段PHP会根据php.ini的配置将对应的扩展共享库加载到PHP中。

# 开发工具

PHP提供了几个用于简化扩展开发的脚本工具:

  • ext_skel:初始化php扩展项目
  • phpsize:生成configure配置文件

# ext_skel

ext_skel这个脚本位于php源码的ext目录下,它的作用是用来生成扩展的基本骨架,帮助开发者快速生成一个规范的扩展结构。

用法如下(以新建say扩展为例):

gitlib@devops:~/php-7.1.31/ext$ ./ext_skel --extname=say
1

执行完之后在ext目录下新生成一个扩展目录,比如

gitlib@devops:~/php-7.1.31/ext/say$ ls -al
total 44
drwxr-xr-x  3 zhoufei root 4096 Oct  6 21:46 .
drwxr-xr-x 76 zhoufei root 4096 Oct  6 21:46 ..
-rw-r--r--  1 zhoufei root 1984 Oct  6 21:46 config.m4
-rw-r--r--  1 zhoufei root  331 Oct  6 21:46 config.w32
-rw-r--r--  1 zhoufei root    4 Oct  6 21:46 CREDITS
-rw-r--r--  1 zhoufei root    0 Oct  6 21:46 EXPERIMENTAL
-rw-r--r--  1 zhoufei root  392 Oct  6 21:46 .gitignore
-rw-r--r--  1 zhoufei root 2267 Oct  6 21:46 php_say.h
-rw-r--r--  1 zhoufei root 5023 Oct  6 21:46 say.c
-rw-r--r--  1 zhoufei root  493 Oct  6 21:46 say.php
drwxr-xr-x  2 zhoufei root 4096 Oct  6 21:46 tests
1
2
3
4
5
6
7
8
9
10
11
12
13

主要文件说明如下:

  • config.m4:autoconf规则的编译配置文件
  • include:依赖库的include头文件
  • say.c:扩展源码
  • php_say.c: 扩展源码头文件

这个脚本主要生成来编译需要的配置及扩展的基本结构,初步生成的这个扩展可以成功编译、安装和使用,实际开发中我们可以用这个脚本生成一个基本结构,然后根据具体的需要完善。

# phpize

phpsize是扩展编译必用的一个脚本,主要是操作复杂的autoconf/automake/autoheader/autolocal等系列命令,用于生成扩展的configure文件。

示例:

gitlib@devops:~/php-7.1.31/ext/say$ /usr/local/php7/bin/phpize 
Configuring for:
PHP Api Version:         20180731
Zend Module Api No:      20180731
Zend Extension Api No:   320180731
1
2
3
4
5

# 实践案例

示例中,我们将实现如下功能:

<?php
echo say();
?>
1
2
3

输出内容:

$ php ./test.php
$ hello word
1
2

在扩展中实现一个say方法,调用say方法后,输出 hello word。

# 第一步:生成代码

PHP为我们提供了生成基本代码的工具 ext_skel。这个工具在PHP源代码的./ext目录下。

$ cd php_src/ext/
$ ./ext_skel --extname=say
1
2

extname参数的值就是扩展名称,执行ext_skel命令后,这样在当前目录下会生成一个与扩展名一样的目录。

# 第二步,修改config.m4配置文件

$ cd ./say
$ vim ./config.m4
1
2

config.m4的作用就是配合phpize工具生成configure文件。configure文件是用于环境检测的。检测扩展编译运行所需的环境是否满足,现在开始修改config.m4文件。

打开config.m4文件后,你会发现这样一段文字:

dnl If your extension references something external, use with:

dnl PHP_ARG_WITH(say, for say support,
dnl Make sure that the comment is aligned:
dnl [  --with-say             Include say support])

dnl Otherwise use enable:

dnl PHP_ARG_ENABLE(say, whether to enable say support,
dnl Make sure that the comment is aligned:
dnl [  --enable-say           Enable say support])
1
2
3
4
5
6
7
8
9
10
11

其中,dnl 是注释符号。上面的代码说,如果你所编写的扩展如果依赖其它的扩展或者lib库,需要去掉PHP_ARG_WITH相关代码的注释。否则,去掉 PHP_ARG_ENABLE 相关代码段的注释。我们编写的扩展不需要依赖其他的扩展和lib库。因此,我们去掉PHP_ARG_ENABLE前面的注释。去掉注释后的代码如下:

dnl If your extension references something external, use with:

dnl PHP_ARG_WITH(say, for say support,
dnl Make sure that the comment is aligned:
dnl [  --with-say             Include say support])

dnl Otherwise use enable:

PHP_ARG_ENABLE(say, whether to enable say support,
Make sure that the comment is aligned:
[  --enable-say           Enable say support])
1
2
3
4
5
6
7
8
9
10
11

# 第三步,代码实现

修改say.c文件。实现say方法。

找到PHP_FUNCTION(confirm_say_compiled),在其上面增加如下代码:

PHP_FUNCTION(say)
{
    zend_string *strg;
    strg = strpprintf(0, "hello word");
    RETURN_STR(strg);
}
1
2
3
4
5
6

找到PHP_FE(confirm_say_compiled, 在上面增加如下代码:

 PHP_FE(say, NULL)
1

修改后的代码如下:

const zend_function_entry say_functions[] = {
	PHP_FE(say, NULL)       /* For testing, remove later. */
	PHP_FE(confirm_say_compiled,    NULL)       /* For testing, remove later. */
	PHP_FE_END  /* Must be the last line in say_functions[] */
};

/* }}} */
1
2
3
4
5
6
7

# 第四步,编译安装

编译扩展的步骤如下:

$ phpize
$ ./configure
$ make && make install
1
2
3

修改php.ini文件,增加如下代码:

[say]
extension = say.so
1
2

然后执行,php -m 命令,在输出的内容中,会看到say字样。

# 第五步,调用测试

写一个脚本,调用say方法,看输出的内容是否符合预期。

# 总结

总结一下编写扩展的步骤:

  • **初始化:**通过ext目录下的ext_skel脚本生成扩展的基本扩展ext_skel -extname;
  • **修改config.m4配置:**设置编译配置参数、设置扩展的源代码、依赖库/函数检查等;
  • **编写扩展要实现的功能:**按照PHP扩展的格式及PHP提供的api编写功能;
  • **生成configure:**扩展编写完成后执行phpsize脚本生成configure及其他配置文件;
  • 编译&安装:./configure、make、make install,然后将扩展的.so路径添加到php.ini中;
#PHP
上次更新: 2022/12/01, 11:09:34
PHP框架常见URL模式
PHP垃圾回收机制

← PHP框架常见URL模式 PHP垃圾回收机制→

最近更新
01
常用游戏反外挂技术总结
11-27
02
Golang开发实践万字总结
11-11
03
Redis万字总结
10-30
更多文章>
Theme by Vdoing | Copyright © 2011-2022 Ravior | 粤ICP备17060229号-3 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式