5、扩展骨架文件内容

女主宣言

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

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

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

“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"; then
    AC_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_H

extern 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_OPTIONAL
        Z_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();
#endif

    return 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等众多技术领域,通过夯实的技术积累和丰富的一线实战经验,为你带来最有料的技术分享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值