• php扩展如何嵌入到php框架中


    编写一个简单的扩展示例

    使用php内置工具生成自定义扩展的框架。该工具在ext文件夹下面

    ./ext_skel --extname=wully

    Ext_skel的主要参数(这里面只列举了最常用的两个)

      --extname=module   module is the name of your extension【必须有的】

    生成模块的名称,会自动在ext内建立extname文件夹,最常用的

      --proto=file       file contains prototypes of functions to create【可选】

    函数原型定义文件

    官方说明地址:

    http://www.php.net/manual/en/internals2.buildsys.skeleton.php

    修正ext/wully/config.m4

    修正后,运行:

    ./buildconf --force

    ./configure --enable-wully

    Make & make install 及可以安装成功

    可以通过运行 ext/wully/wully.php来校验是否安装成功

    扩展的内部实现


    依旧以生成的wully模块为例,这个模块的提供的外部函数在

    const zend_function_entry wully_functions[]这里面陈列(wully.c),我们可以看到示例中定义的函数为

    PHP_FE(confirm_wully_compiled,  NULL)

    这个模块的外部函数和模块在php请求各个阶段的调用逻辑是通过

    wully_module_entry(zend_module_entry)结构传给php框架的

    php扩展函数的实现逻辑

    每一个扩展函数都是通过PHP_FUNCTION来实现的,例如我们的示例,通过PHP_FUNCTION(confirm_wully_compiled) 来实现的

    内部如何获取php函数的参数

    生成的源码函数为:

    zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len)

    这个是一个参数,且参数类型为字符串的情况

     

    调用的原型为:

    zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, …);

    有两个参数我们要特别注意下:

    第一个参数为该函数获取的参数个数

    第三个参数为php函数传过来的参数类型,下表是一个对应关系图

    后面的参数则是参数的值,及参数的大小,第二个参数对应于线程安全,这里面先不关心

    参数类型对应表

    类型指定符

    对应的C类型

    描述

    l

    long

    符号整数

    d

    double

    浮点数

    s

    char *, int

    二进制字符串,长度

    b

    zend_bool

    逻辑型(1或0)

    r

    zval *

    资源(文件指针,数据库连接等)

    a

    zval *

    联合数组

    o

    zval *

    任何类型的对象

    O

    zval *

    指定类型的对象。需要提供目标对象的类类型

    z

    zval *

    无任何操作的zval

    再看一个三个参数,一个为字符串,两个为整数

    zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &arg, &arg_len,&n,&m)

     PHP_FUNCTION展开模式:

    #define PHP_FUNCTION        ZEND_FUNCTION

    #define ZEND_FUNCTION(name)        ZEND_NAMED_FUNCTION(ZEND_FN(name))

    #define ZEND_FN(name) zif_##name

    #define ZEND_NAMED_FUNCTION(name)        void name(INTERNAL_FUNCTION_PARAMETERS)

    #define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC

    提供外部函数列表的展开模式,即PHP_FE

    #define PHP_FE          ZEND_FE

    #define ZEND_FE(name, arg_info)        ZEND_FENTRY(name, ZEND_FN(name), arg_info, 0)

    #define ZEND_FENTRY(zend_name, name, arg_info, flags)        { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },

    按照php处理请求的各个阶段我们分为 mint rint   script rshutdown mshutdown,我们自定义的外部扩展对请求的各个阶段也可以进行相应的干预。


    各个阶段的干预接口为:


    MINIT阶段:模块初始化阶段

    对应PHP_MINIT(wully)的实现

    sapistart阶段,调用zend_startup_module

    ZEND_API int zend_startup_module(zend_module_entry *module)执行两个动作注册模块,启动模块

    注册模块

    zend_register_internal_module(module TSRMLS_CC)

    把module放入 module_registry 中,其中 module_registry 为一个全局的hash tab

    启动模块

    zend_startup_module_ex(module TSRMLS_CC) == SUCCESS

    检测依赖是否就绪,然后运行该module PHP_MINIT函数

    MINIT宏展开模式:

    #define PHP_MINIT                ZEND_MODULE_STARTUP_N

    #define ZEND_MINIT                        ZEND_MODULE_STARTUP_N

    #define ZEND_MODULE_STARTUP_N(module)       zm_startup_##module

    RINIT阶段:请求初始化

    对应PHP_RINIT(wully)的实现

    int php_request_startup(TSRMLS_D)

    void zend_activate_modules(TSRMLS_D)

    int module_registry_request_startup(zend_module_entry *module TSRMLS_DC)

    module->request_startup_func(module->type, module->module_number TSRMLS_CC)

    RINIT宏展开模式

    #define PHP_RINIT  ZEND_MODULE_ACTIVATE_N

    #define ZEND_RINIT  ZEND_MODULE_ACTIVATE_N

    #define ZEND_MODULE_ACTIVATE_N(module)  zm_activate_##module

    script阶段

    我们的PHP_FUNCTION执行在script阶段,他们作为php语言编译和解释的一部分,纳入到opcode的执行中

    PHP_RSHUTDOWN阶段:请求关闭

    对应PHP_RSHUTDOWN(wully))的实现

    void php_request_shutdown(void *dummy)

    void zend_deactivate_modules(TSRMLS_D)

    int module_registry_cleanup(zend_module_entry *module TSRMLS_DC)

    module->request_shutdown_func(module->type, module->module_number TSRMLS_CC)

    PHP_RSHUTDOWN        宏展开模式

    #define PHP_RSHUTDOWN            ZEND_MODULE_DEACTIVATE_N

    #define ZEND_MODULE_DEACTIVATE_N(module)        zm_deactivate_##module

    PHP_MSHUTDOWN阶段:模块关闭

    对应PHP_MSHUTDOWN(wully))的实现

    zend_startup中注册模块销毁时的析构函数

    int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC)

    zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);

    #define ZEND_MODULE_DTOR (void (*)(void *)) module_destructor

    void module_destructor(zend_module_entry *module)

    module->module_shutdown_func(module->type, module->module_number TSRMLS_CC);

    PHP_MSHUTDOWN           宏展开模式

    #define PHP_MSHUTDOWN            ZEND_MODULE_SHUTDOWN_N

    #define ZEND_MODULE_SHUTDOWN_N(module)  zm_shutdown_##module

    PHP_MINFO跟前面的宏意义有所不同,主要用于在phpinfo中显示模块的信息

    #define PHP_MINFO                ZEND_MODULE_INFO_N

    #define ZEND_MINFO                        ZEND_MODULE_INFO_N

  • 相关阅读:
    scrapy 模块功能流程--转
    CP三次握手和四次分手--转
    获取免费IP--代码--转
    爬虫介绍+Jupyter Notebook--转
    In Ubuntu, How to install Chinese Pinyin with Fcitx?
    对json文件进行简单读写操作
    ubuntu 中wget (下载)命令用法
    如何更改Ubuntu 16.04 默认Python版本方法
    如何将本地文件上传通过命令行命令上传到远程服务器上
    Ubuntu上,如何成功的安装pygrib
  • 原文地址:https://www.cnblogs.com/wully/p/2332667.html
Copyright © 2020-2023  润新知