编写一个简单的扩展示例
   使用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)的实现
   在sapi的start阶段,调用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
   
 
   