女主宣言

今天小编为大家分享编写PHP扩展的系列文章,文章从环境构建到扩展编写,会对使用到的相关PHP内核数据结构及API进行介绍,希望能对大家有所帮助。

PS:丰富的一线技术、多元化的表现形式,尽在“360云计算”,点关注哦!

  • 1、配置PHP构建环境

  • 2、生成一个PHP扩展框架

  • 3、构建并安装PHP扩展

我们先回顾一下扩展骨架文件的内容。

“config.m4”是扩展配置脚本,在通过“phpize”或“buildconf”命令生成“配置”脚本期间使用。它是用M4宏处理语言编写的。对于PHP扩展配置,非常基础的知识就足够了。可以从本教程或其他扩展配置文件中复制粘贴代码块。

PHP_ARG_ENABLE([test],[whether to enable test support],[AS_HELP_STRING([--enable-test],[Enable test support])],[no])if test "$PHP_TEST" != "no"; thenAC_DEFINE(HAVE_TEST, 1, [ Have test support ])PHP_NEW_EXTENSION(test, test.c, $ext_shared)
fi

PHP_ARG_ENABLE(...) 宏添加配置选项“--enable-test”。它可能会获得三个值“yes”,“no”和“shared”。

当运行“phpize”时,默认值为“shared”,这意味着我们将构建一个可动态加载的PHP扩展。但是,可以将“test”扩展目录复制到主PHP发行版(“ext/test”)中,然后重新运行“./buildconf”和“./configure…–enable-test”以重新构建整个PHP,扩展名为“test”,静态链接。

默认情况下可以启用扩展,在第5行将“no”替换为“yes”。在这种情况下,可以通过“./configure --disable-test”禁用“test”扩展。

在“if”之后的只是一个常规的UNIX shell代码,它测试由“--enable-test”,“--disable-test”或“--enable-test=shared”定义的值。

AC_DEFINE(HAVE_TEST)将C宏HAVE_TEST添加到“config.h”中,因此如有必要,可以使用条件编译指令(#ifdef,#ifndef)跳过无用的代码。

最后,PHP_NEW_EXTENSION(test, test.c, $ext_shared)宏指出,将从“test.c”文件构建扩展“test”。可以指定几个文件。根据$ ext_shared变量的值,扩展名可以构建为共享对象或静态链接。(它取自相同的“--enable-test”选项。)

如果添加新的源文件或需要链接某些外部库,则可能需要扩展此文件。稍后将说明如何链接库。只是,不要忘记在此文件中进行任何更改后重新运行“phpize” / “buildconf” +“configure”。

Windows PHP使用不同的构建系统。对于Windows,文件“config.w32”代替了“config.m4”。两者几乎相同。他们使用相似的宏,只是一种不同的语言:在Windows PHP构建系统上,使用JavaScript而不是M4和Shell。将不再重复对宏的解释。

ARG_ENABLE('test', 'test support', 'no');if (PHP_TEST != 'no') {AC_DEFINE('HAVE_TEST', 1, 'test support enabled');EXTENSION('test', 'test.c', null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
}

“php_test.h”是具有通用定义的C头文件。在我们最基本的情况下,它定义:

  • test_module_entry — 扩展描述结构。(扩展程序的入口)

  • PHP_TEST_VERSION — 扩展的版本。

  • ZEND_TSRMLS_CACHE_EXTERN — 如果扩展是为线程安全的版本(ZTS)构建并编译为共享对象(COMPILE_DL_TEST),则为线程本地存储缓存条目。

/* test extension for PHP */#ifndef PHP_TEST_H
# define PHP_TEST_Hextern zend_module_entry test_module_entry;
# define phpext_test_ptr &test_module_entry# define PHP_TEST_VERSION "0.1.0"# if defined(ZTS) && defined(COMPILE_DL_TEST)
ZEND_TSRMLS_CACHE_EXTERN()
# endif#endif   /* PHP_TEST_H */

“test.c”是主要扩展源文件。我们将其分成小部分来分别解释。

/* test extension for PHP */#ifdef HAVE_CONFIG_H
# include "config.h"
#endif#include "php.h"
#include "ext/standard/info.h"
#include "php_test.h"

包括必要的C头文件。如有必要,可以添加其他“#include”指令。

/* For compatibility with older PHP versions */
#ifndef ZEND_PARSE_PARAMETERS_NONE
#define ZEND_PARSE_PARAMETERS_NONE() \ZEND_PARSCE_PARAMETERS_START(0, 0) \ZEND_PARSE_PARAMETERS_END()
#endif

一些向前兼容性宏,以便可以为较旧的PHP-7版本编译扩展。

/* {{{ void test_test1()*/
PHP_FUNCTION(test_test1)
{ZEND_PARSE_PARAMETERS_NONE();php_printf("The extension %s is loaded and working!\r\n", "test");
}
/* }}} */

我们的PHP扩展提供的功能test_test1()的C代码。PHP_FUNCTION()宏的参数是函数名称。ZEND_PARSE_PARAMETERS_NONE()表示此函数不需要任何参数。php_printf(...)只是一个C函数调用,该函数将字符串打印到输出流中,类似于PHP printf()函数。

/* {{{ string test_test2( [ string $var ] )*/
PHP_FUNCTION(test_test2)
{char *var = "World";size_t var_len = sizeof("World") – 1;zend_string *retval;ZEND_PARSE_PARAMETERS_START(0, 1)Z_PARAM_OPTIONALZ_PARAM_STRING(var, var_len)ZEND_PARSE_PARAMETERS_END();retval = strpprintf(0, "Hello %s", var);RETURN_STR(retval);
}
/* }}}*/

另一个更复杂的函数使用“快速参数解析API”来描述其参数。

ZEND_PARSE_PARAMETERS_START(0, 1)启动参数描述部分。它的第一个参数(0)定义所需参数的数量。

第二个自变量(1)定义最大自变量数。因此,我们的函数可以不带参数调用,也可以带单个参数调用。

在本节中,我们应该定义所有参数,它们的类型以及将它们复制到的位置。对于我们的情况:

  • Z_PARAM_OPTIONAL 将必需的参数与可选的参数分开。

  • Z_PARAM_STRING() 定义一个字符串参数,该值将被复制到变量“var”,将长度复制到变量“var_len”。

请注意,我们的参数是可选的,因此可以省略。在这种情况下,将使用默认值“world”。参见ZEND_PARSE_PARAMETERS_START上方的变量“var”和“var_len”的初始化程序。

该代码创建一个“zend_string”值,并通过类似于PHP sprintf() 函数的宏RETURN_STR()返回该值:

/* {{{ PHP_RINIT_FUNCTION*/
PHP_RINIT_FUNCTION(test)
{
#if defined(ZTS) && defined(COMPILE_DL_TEST)ZEND_TSRMLS_CACHE_UPDATE();
#endifreturn SUCCESS;
}
/* }}} */

PHP_RINIT_FUNCTION()定义了一个回调函数,它将在每次请求启动时被调用。在我们的情况下,它仅初始化线程本地存储缓存。尽早进行此操作(在MINIT或GINIT回调中)会更好。预计这将在PHP 8扩展框架中得到解决。

/* {{{ PHP_MINFO_FUNCTION*/
PHP_MINFO_FUNCTION(test)
{php_info_print_table_start();php_info_print_table_header(2, "test support", "enabled");php_info_print_table_end();
}
/* }}} */

PHP_MINFO_FUNCTION()定义了一个回调函数,该函数将从PHP phpinfo()函数中调用,以打印有关扩展的信息。

/* {{{ arginfo*/
ZEND_BEGIN_ARG_INFO(arginfo_test_test1, 0)
ZEND_END_ARG_INFO()

有关第一个函数的参数的信息。没有参数。

ZEND_BEGIN_ARG_INFO(arginfo_test_test2, 0)ZEND_ARG_INFO(0, str)
ZEND_END_ARG_INFO()
/* }}} */

有关第二个函数的参数的信息。名称为“str”的单个可选参数按值传递。

/* {{{ test_functions[]*/
static const zend_function_entry test_functions[] = {PHP_FE(test_test1,        arginfo_test_test1)PHP_FE(test_test2,       arginfo_test_test2)PHP_FE_END
};
/* }}} */

“test_functions”是所有扩展功能的列表,以及有关其参数的信息。该列表由PHP_FE_END宏终止。

/* {{{ test_module_entry*/
zend_module_entry test_module_entry = {STANDARD_MODULE_HEADER,"test",                /* Extension name */test_functions,         /* zend_function_entry */NULL,              /* PHP_MINIT - Module initialization */NULL,                /* PHP_MSHUTDOWN - Module shutdown */PHP_RINIT(test),           /* PHP_RINIT - Request initialization */NULL,               /* PHP_RSHUTDOWN - Request shutdown */PHP_MINFO(test),          /* PHP_MINFO - Module info */PHP_TEST_VERSION,          /* Version */STANDARD_MODULE_PROPERTIES
};
/* }}} */

test_module_entry 是主要的扩展条目结构。PHP核心从此类结构获取有关扩展的所有信息。它定义:

  • 扩展名(“test”)。

  • 声明的PHP函数列表(“test_functions”)。

  • 一些回调函数和扩展版本(PHP_TEST_VERSION-在头文件中定义)。

回调发生在以下情况:当PHP启动(MINIT),PHP终止(MSHUTDOWN),每个请求处理的开始(RINIT),每个请求处理的结束(RSHUTDOWN)以及来自phpinfo()(MINFO)的回调。

#ifdef COMPILE_DL_TEST
# ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
# endif
ZEND_GET_MODULE(test)
#endif

最后,为动态链接的两个定义。

如果大家有什么建议或疑问,可以在下方留言交流。

360云计算

由360云平台团队打造的技术分享公众号,内容涉及数据库、大数据、微服务、容器、AIOps、IoT等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享

5、扩展骨架文件内容相关推荐

  1. Linux里如何查找文件内容 grep

    Linux查找文件内容的常用命令方法. 从文件内容查找匹配指定字符串的行: $ grep "被查找的字符串" 文件名 例子:在当前目录里第一级文件夹中寻找包含指定字符串的.in文件 ...

  2. python 读取文件读出来是什么格式-深入学习python解析并读取PDF文件内容的方法...

    这篇文章主要学习了python解析并读取PDF文件内容的方法,包括对学习库的应用,python2.7和python3.6中python解析PDF文件内容库的更新,包括对pdfminer库的详细解释和应 ...

  3. python中读取文件内容-深入学习python解析并读取PDF文件内容的方法

    这篇文章主要学习了python解析并读取PDF文件内容的方法,包括对学习库的应用,python2.7和python3.6中python解析PDF文件内容库的更新,包括对pdfminer库的详细解释和应 ...

  4. linux下使用find xargs grep查找文件及文件内容

    原文地址:http://sundful.iteye.com/blog/1730385 1,在某个路径下查文件. 在/etc下查找"*.log"的文件 find /etc -name ...

  5. jq 比较两个时间是否在同一天_.NET CORE下最快比较两个文件内容是否相同的方法...

    最近项目有个需求,需要比较两个任意大小文件的内容是否相同,要求如下: 项目是.NET CORE,所以使用C#进行编写比较方法 文件大小任意,所以不能将文件内容全部读入到内存中进行比较(更专业点说,需要 ...

  6. python修改文件内容最后一行_关于python:如何修改文件的最后一行?

    我文件的最后一行是: 29-dez,40, 号 如何修改该行,使其显示: 29-Dez,40,90,100,50 号 注意:我不想写新行.我想在29-Dez,40,后面加一行新值. 我是Python的 ...

  7. 3.1 cat:合并文件或查看文件内容

    cat 命令 可以理解为英文单词concatenate的缩写,其功能是连接多个文件并且打印到屏幕输出,或者重定向到指定的文件中.此命令常用来显示单个文件内容,或者将几个文件内容连接起来一起显示,还可以 ...

  8. DOS 中for遍历文件内容

    http://blog.neu.edu.cn/elm/archives/104 以前常觉得DOS的命令行功能太弱,无法象UNIX一样可以用命令行完成非常复杂的操作.实际上,当MS从WIN2K开始将命令 ...

  9. SmartUpload上传下载及文件名和文件内容中文问题

    一.安装篇 jspSmartUpload是由www.jspsmart.com网站开发的一个可免费使用的全功能的文件上传下载组件,适于嵌入执行上传下载操作的JSP文件中.该组件有以下几个特点: 1.使用 ...

最新文章

  1. 机器学习模型调参指南(附代码)
  2. 皮一皮:这是仙女用的嘛?
  3. PHP获取IP的多种方式解析
  4. C++中的空类与空结构体大小
  5. servlet和jsp页面过滤器Filter的作用及配置
  6. python变量定义问题_python 定义n个变量方法 (变量声明自动化)
  7. 统计学(可汗学院视频62-81集笔记)
  8. Silverlight入门:第五部分 - 整合其它控件
  9. Snipaste2.7.3下载安装与使用(超实用的截图利器)
  10. FLOW 3D二次开发
  11. python创建简单网站
  12. 太飒了!这届乘风破浪的 IT 女神写得了代码、撕得掉年龄、跨得过行业!
  13. 验证码(CAPTCHA)
  14. 用Multisim 14.1实现逻辑函数的化简与变换
  15. 微信java tools_微信工具weixin-java-tools的使用总结
  16. 2022年湖南省临床执业医师考试二单元随机真题
  17. python画图横坐标_python画图把时间作为横坐标的方法
  18. 用java解一元二次方程组
  19. Excel/WPS 按条件合并多行
  20. Win7 各种语言包下载

热门文章

  1. Android中的Context理解
  2. PHP学习之路之Hello World小程序
  3. 03. 数组中重复的数字
  4. HBase的BulkLoad详解
  5. 解决layui laydate动态创建多个时不起作用点击无效的问题
  6. java程序运行时,数据的存储地!
  7. Mysql排序添加名词_记面试中问到的MySQL的SQL调优问题
  8. Linux下用户、组、权限操作
  9. 添加一列_快速给电子书pdf添加书签
  10. java 树形图构建