php扩展开发一:hello world

简介: php扩展开发一:hello world

下载php源码

首先,我们需要下载php的源码:https://github.com/php/php-src/releases

本人选择的是php7.3

wget https://github.com/php/php-src/archive/php-7.3.3.tar.gz

自行选择版本,下载完之后解压,并进入php目录 ext/

tar -zvxf php-7.3.3.tar.gz
cd php-src-php-7.3.3/ext

在这个目录中,有个"ext_skel.php"的文件,我们运行:

php ext_skel.php --ext tioncico

将输出:

\[root@localhost ext\]# php ext_skel.php --ext tioncico
Copying config scripts... done
Copying sources... done
Copying tests... done
Success. The extension is now ready to be compiled into PHP. To do so, use the
following steps:
cd /path/to/php-src
./buildconf
./configure --enable-tioncico
make
Don't forget to run tests once the compilation is done:
make test TESTS=ext/tioncico/tests
Thank you for using PHP!

在这个时候,将会生成一个和扩展名一样的文件夹

准备工作结束了

扩展目录

进入扩展文件夹

cd tioncico

里面有以下几个文件:

tests  //文件夹,用于扩展安装之后的测试
config.m4  //配置编译的执行命令
config.w32  //win32编译
php_tioncico.h //扩展的头文件  
tioncico.c //扩展c文件

安装扩展

我们直接通过phpize生成./configure文件:(多版本情况需要注意phpize版本)

phpize

然后根据正常的安装扩展进行安装:

./configure --with-php-config=/www/server/php/73/bin/php-config
make
make install

在编译完成之后,在php.ini中加入一行配置:

extension = tioncico.so

php -m查看扩展是否安装:

php -m

进入tests文件夹,运行测试文件:

cd tests
php 001.phpt 
php 002.phpt 
php 003.phpt

即可看到自定义扩展的输出(本人是php多版本,所以用的是php73版本运行)

\[root@localhost tests\]# php73 001.phpt 
--TEST--
Check if tioncico is loaded
--SKIPIF--
--FILE--
The extension "tioncico" is available--EXPECT--
The extension "tioncico" is available
\[root@localhost tests\]# php73 002.phpt 
--TEST--
tioncico_test1() Basic test
--SKIPIF--
--FILE--
The extension tioncico is loaded and working!
NULL
--EXPECT--
The extension tioncico is loaded and working!
NULL
\[root@localhost tests\]# php73 003.phpt 
--TEST--
tioncico_test2() Basic test
--SKIPIF--
--FILE--
string(11) "Hello World"
string(9) "Hello PHP"
--EXPECT--
string(11) "Hello World"
string(9) "Hello PHP"

config.m4

网上的教程都说到,运行hello world扩展需要去掉

PHP_ARG_ENABLE(tioncico, whether to enable tioncico support,

dnl Make sure that the comment is aligned:

[ --enable-tioncico Enable tioncico support], no)

这三行的dnl注释,但是本人运行php73生成扩展时默认就去掉了上下2行注释,中间那行并不需要

PHP_ARG_ENABLE和PHP_ARG_WITH代表了2种编译模式

PHP_ARG_WITH 在你的扩展用到外部依赖的时候需要使用

否则使用PHP_ARG_ENABLE

之后我或许会继续学习下去补充说明

php_tioncico.h

该文件为扩展头文件,用于定义声明php扩展

extern zend\_module\_entry tioncico\_module\_entry;

该行代码引用了php源码的模块必要信息结构体

struct \_zend\_module_entry {
   unsigned short size;
   unsigned int zend_api;
   unsigned char zend_debug;
   unsigned char zts;
   const struct \_zend\_ini\_entry *ini\_entry;
   const struct \_zend\_module_dep *deps;
   const char *name;//扩展名
   const struct \_zend\_function_entry *functions;//php函数结构体的指针
   int (*module\_startup\_func)(INIT\_FUNC\_ARGS);//模块初始化时被调用的函数指针。用来放一些初始化步骤。初始化过程中出现故障返回FAILURE,成功返回SUCCESS。声明一个初始化函数使用ZEND_MINIT
   int (*module\_shutdown\_func)(SHUTDOWN\_FUNC\_ARGS);//模块被关闭时调用的函数指针,同来用来做一次性的析构步骤。如释放资源。成功返回SUCESS,失败返回FAILURE,未使用返回NULL。声明使用ZEND_MSHUTDOWN
   int (*request\_startup\_func)(INIT\_FUNC\_ARGS);//每处理一次请求前调用此函数。成功SUCESS,失败FAILURE,未使用返回NULL。声明使用ZEND_RINIT。从WEB来解释,就是每次请求调用此函数。
   int (*request\_shutdown\_func)(SHUTDOWN\_FUNC\_ARGS);//每处理一次请求结束后调用此函数。成功SUCESS,失败FAILURE,未使用返回NULL。声明使用ZEND_RSHUTDOWN。
   void (*info\_func)(ZEND\_MODULE\_INFO\_FUNC\_ARGS);//当调用phpinfo()时打印出的关于此扩展的信息。这个信息就是由此函数来输出的。声明使用ZEND\_MINFO
   const char *version;//版本号
   size\_t globals\_size;
#ifdef ZTS
   ts\_rsrc\_id* globals\_id\_ptr;
#else
   void* globals_ptr;
#endif
   void (\*globals_ctor)(void \*global);
   void (\*globals_dtor)(void \*global);
   int (*post\_deactivate\_func)(void);
   int module_started;
   unsigned char type;
   void *handle;
   int module_number;
   const char *build_id;
};

tioncico.c

该文件为扩展的主文件,里面写我们需要实现的扩展逻辑

里面默认已经写好了例子以及入口

首先我们需要看下zend_module_entry tioncico_module_entry

/* {{{ tioncico\_module\_entry
 * 模块信息结构体
 */
zend\_module\_entry tioncico\_module\_entry = {
   STANDARD\_MODULE\_HEADER,//标准模块头,填充了扩展名上面的所有参数
   "tioncico",                /* 扩展名
   tioncico_functions,          /* 函数定义
   NULL,                    /* PHP_MINIT - Module initialization */
   NULL,                    /* PHP_MSHUTDOWN - Module shutdown */
   PHP\_RINIT(tioncico),         /* PHP\_RINIT - Request initialization */
   NULL,                    /* PHP_RSHUTDOWN - Request shutdown */
   PHP\_MINFO(tioncico),         /* PHP\_MINFO - Module info */
   PHP\_TIONCICO\_VERSION,     /* Version 在tioncico.h中已经定义了版本号*/
   STANDARD\_MODULE\_PROPERTIES //标准模块属性充了版本号下面的所有参数
};
/* }}} */

通过上面的函数定义结构体,我们需要声明自己的函数:

/* {{{ void tioncico_test1()
 */
PHP\_FUNCTION(tioncico\_test1)
{
   ZEND\_PARSE\_PARAMETERS_NONE();//暂时不确定详细意思,大概为没有参数的情况需要调用这个
   php_printf("The extension %s is loaded and working!\\r\\n", "tioncico");//直接输出字符串,相当于php echo
}

我们也可以声明一个带参数的函数:

/* {{{ string tioncico_test2( \[ string $var \] )
 */
PHP\_FUNCTION(tioncico\_test2)
{
   char *var = "World";//定义一个world字符串变量
   size\_t var\_len = sizeof("World") - 1;//定义长度
   zend\_string *retval;//定义zend\_string类型的变量
   ZEND\_PARSE\_PARAMETERS_START(0, 1)//设置参数数量限制,前面的代表着最少传0个参数,后面的代表了最多传1个
      Z\_PARAM\_OPTIONAL //可选参数 ,不强制传参
      Z\_PARAM\_STRING(var, var_len)//如果有传值,则把值赋值给字符串变量var
   ZEND\_PARSE\_PARAMETERS_END();//设置参数结束
   retval = strpprintf(0, "Hello %s", var);//格式化字符串
   RETURN_STR(retval);//返回值
}
/* }}}*/

但这样是不够的,我们还需要定义一个函数的参数声明:

/* {{{ arginfo
 */
ZEND\_BEGIN\_ARG\_INFO(arginfo\_tioncico_test1, 0)//函数名,参数是否为引用类型,0代表不是
ZEND\_END\_ARG_INFO()//结束函数参数信息声明
ZEND\_BEGIN\_ARG\_INFO(arginfo\_tioncico_test2, 0)//函数名,参数是否为引用类型,0代表不是
   ZEND\_ARG\_INFO(0, str)//声明一个普通参数str
ZEND\_END\_ARG_INFO()//结束函数参数信息声明
/* }}} */

然后,将函数注册进模块

/* {{{ tioncico_functions\[\]
 */
static const zend\_function\_entry tioncico_functions\[\] = {
   PHP\_FE(tioncico\_test1,    arginfo\_tioncico\_test1)
   PHP\_FE(tioncico\_test2,    arginfo\_tioncico\_test2)
   PHP\_FE\_END
};

这时候,一个扩展的2个函数已经编写完成了

重新编译运行,调用函数即可:

\[root@localhost tioncico\]# php73 tests/002.phpt 
--TEST--
tioncico_test1() Basic test
--SKIPIF--
--FILE--
tioncico is 666! //修改过的输出
NULL
--EXPECT--
The extension tioncico is loaded and working!
NULL


目录
相关文章
|
数据采集 存储 缓存
PHP爬虫的使用与开发
本文深入探讨了PHP爬虫的使用与开发,涵盖基本原理、关键技术、开发实践及优化策略。从发送HTTP请求、解析HTML到数据存储,再到处理反爬机制,全面指导读者构建高效可靠的爬虫程序。
239 3
|
5月前
|
安全 PHP
PHP 8 新特性实战:提升开发效率的利器
PHP 8 新特性实战:提升开发效率的利器
207 87
|
5月前
|
安全 PHP
PHP 8 新特性实战:提升开发效率的利器
PHP 8 新特性实战:提升开发效率的利器
213 88
|
5月前
|
安全 编译器 PHP
PHP 8 新特性:现代开发的强力引擎
PHP 8 新特性:现代开发的强力引擎
206 89
|
5月前
|
安全 编译器 PHP
PHP 8 新特性:现代化开发的飞跃
PHP 8 新特性:现代化开发的飞跃
298 89
|
5月前
|
安全 大数据 PHP
PHP 7+ 新特性实战指南:提升开发效率
PHP 7+ 新特性实战指南:提升开发效率
219 87
|
3月前
|
消息中间件 人工智能 Java
抖音微信爆款小游戏大全:免费休闲/竞技/益智/PHP+Java全筏开源开发
本文基于2025年最新行业数据,深入解析抖音/微信爆款小游戏的开发逻辑,重点讲解PHP+Java双引擎架构实战,涵盖技术选型、架构设计、性能优化与开源生态,提供完整开源工具链,助力开发者从理论到落地打造高留存、高并发的小游戏产品。
|
9月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
489 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
7月前
|
存储 消息中间件 前端开发
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
校园圈子系统校园论坛小程序采用uni-app前端框架,支持多端运行,结合PHP后端(如ThinkPHP/Laravel),实现用户认证、社交关系管理、动态发布与实时聊天功能。前端通过组件化开发和uni.request与后端交互,后端提供RESTful API处理业务逻辑并存储数据于MySQL。同时引入Redis缓存热点数据,RabbitMQ处理异步任务,优化系统性能。核心功能包括JWT身份验证、好友系统、WebSocket实时聊天及活动管理,确保高效稳定的用户体验。
441 4
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
ly~
|
存储 供应链 小程序
除了微信小程序,PHP 还可以用于开发哪些类型的小程序?
除了微信小程序,PHP 还可用于开发多种类型的小程序,包括支付宝小程序、百度智能小程序、抖音小程序、企业内部小程序及行业特定小程序。在电商、生活服务、资讯、工具、娱乐、营销等领域,PHP 能有效管理商品信息、订单处理、支付接口、内容抓取、复杂计算、游戏数据、活动规则等多种业务。同时,在企业内部,PHP 可提升工作效率,实现审批流程、文件共享、生产计划等功能;在医疗和教育等行业,PHP 能管理患者信息、在线问诊、课程资源、成绩查询等重要数据。
ly~
322 6