略微加速

略速 - 互联网笔记

php扩展开发

2021-03-26 leiting (1725阅读)

标签 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


原文:http://www.php20.cn/article/sw/%E6%89%A9%E5%B1%95/177


北京半月雨文化科技有限公司.版权所有 京ICP备12026184号-3