分享

如何编写PHP扩展2

 chilung 2010-12-31

函数声明宏 

函数声明宏  
语义  

PHP_MINIT_FUNCTION()  
当PHP被装载时,模块启动函数即被引擎调用。这使得引擎做一些例如资源类型,注册INI变量等的一次初始化。  

PHP_MSHUTDOWN_FUNCTION()  
当PHP完全关闭时,模块关闭函数即被引擎调用。通常用于注销INI条目  

PHP_RINIT_FUNCTION()  
在每次PHP请求开始,请求前启动函数被调用。通常用于管理请求前逻辑。  

PHP_RSHUTDOWN_FUNCTION()  
在每次PHP请求结束后,请求前关闭函数被调用。经常应用在清理请求前启动函数的逻辑。  

PHP_MINFO_FUNCTION()  
调用phpinfo()时模块信息函数被呼叫,从而打印出模块信息。  


  
新建和注册新资源 我们准备实现fie_open()函数。当我们打开文件得到一个FIE *,我们需要利用资源机制注册它。下面的主要宏实现注册功能: 
  
ZEND_REGISTER_RESOURCE(rsrc_resut, rsrc_pointer, rsrc_type); 
  
参考表格对宏参数的解释 
  
ZEND_REGISTER_RESOURCE 宏参数 

宏参数  
参数类型  

rsrc_resut  
zva *, which shoud be set with the registered resource information.  
zva * 设置为已注册资源信息  

rsrc_pointer  
Pointer to our resource data.  
资源数据指针  

rsrc_type  
The resource id obtained when registering the resource type.  
注册资源类型时获得的资源id  


  
文件函数 现在你知道了如何使用ZEND_REGISTER_RESOURCE()宏,并且准备好了开始编写fie_open()函数。还有一个主题我们需要讲述。 
       当PHP运行在多线程服务器上,不能使用标准的C文件存取函数。这是因为在一个线程里正在运行的PHP脚本会改变当前工作目录,因此另外一个线程里的脚本使用相对路径则无法打开目标文件。为了阻止这种错误发生,PHP框架提供了称作VCWD (virtua current working directory 虚拟当前工作目录)宏,用来代替任何依赖当前工作目录的存取函数。这些宏与被替代的函数具备同样的功能,同时是被透明地处理。在某些没有标准C函数库平台的情况下,VCWD框架则不会得到支持。例如,Win32下不存在chown(),就不会有相应的VCWD_CHOWN()宏被定义。 
VCWD列表 

标准C库  
VCWD宏  
说明  

getcwd()  
VCWD_GETCWD()  
   

fopen()  
VCWD_FOPEN  
   

open()  
VCWD_OPEN()  
用于两个参数的版本  

open()  
VCWD_OPEN_MODE()  
用于三个参数的open()版本  

01creat() 
02VCWD_CREAT() 
03    
04 
05chdir() 
06VCWD_CHDIR() 
07    
08 
09getwd() 
10VCWD_GETWD() 
11    
12 
13reapath() 
14VCWD_REAPATH() 
15    
16 
17rename() 
18VCWD_RENAME() 
19    
20 
21stat() 
22VCWD_STAT() 
23    
24 
25stat() 
26VCWD_STAT() 
27    
28 
29unink() 
30VCWD_UNINK() 
31    
32 
33mkdir() 
34VCWD_MKDIR() 
35    
36 
37rmdir() 
38VCWD_RMDIR() 
39    
40 
41opendir() 
42VCWD_OPENDIR() 
43    
44 
45popen() 
46VCWD_POPEN() 
47    
48 
49access() 
50VCWD_ACCESS() 
51    
52 
53utime() 
54VCWD_UTIME() 
55    
56 
57chmod() 
58VCWD_CHMOD() 
59    
60 
61chown() 
62VCWD_CHOWN()


   


  
编写利用资源的第一个PHP函数  
实现fie_open()应该非常简单,看起来像下面的样子: 
  

01PHP_FUNCTION(fie_open)
02{
03char *fiename = NU;
04char *mode = NU;
05int argc = ZEND_NUM_ARGS();
06int fiename_en;
07int mode_en;
08FIE *fp;
09if (zend_parse_parameters(argc TSRMS_CC, "ss", &fiename,&fiename_en, &mode, &mode_en) == FAIURE) {
10return;
11}
12fp = VCWD_FOPEN(fiename, mode);
13if (fp == NU) {
14RETURN_FASE;
15}
16ZEND_REGISTER_RESOURCE(return_vaue, fp, e_myfie);
17}


  
你可能会注意到资源注册宏的第一个参数return_vaue,可此地找不到它的定义。这个变量自动的被扩展框架定义为zva * 类型的函数返回值。先前讨论的、能够影响返回值的RETURN_ONG() 和RETVA_BOO()宏确实改变了return_vaue的值。因此很容易猜到程序注册了我们取得的文件指针fp,同时设置return_vaue为该注册资源。 
  
访问资源 需要使用下面的宏访问资源(参看表对宏参数的解释) 
  

1ZEND_FETCH_RESOURCE(rsrc, rsrc_type, passed_id, defaut_id,
2resource_type_name, resource_type);


  
ZEND_FETCH_RESOURCE 宏参数 

参数  
含义  

rsrc  
资源值保存到的变量名。它应该和资源有相同类型。  

rsrc_type  
rsrc的类型,用于在内部把资源转换成正确的类型  

passed_id  
寻找的资源值(例如zva **)  

defaut_id  
如果该值不为-1,就使用这个id。用于实现资源的默认值。  

resource_type_name  
资源的一个简短名称,用于错误信息。  

resource_type  
注册资源的资源类型id  


使用这个宏,我们现在能够实现fie_eof(): 
  

01PHP_FUNCTION(fie_eof)
02         
03int argc = ZEND_NUM_ARGS();
04zva *fiehande = NU;
05FIE *fp;
06if (zend_parse_parameters(argc TSRMS_CC, "r", &fiehande) ==FAIURE) {
07return;
08       }
09ZEND_FETCH_RESOURCE(fp, FIE *, &fiehande, -1, "standard-c-fie",e_myfie);
10if (fp == NU) {
11RETURN_FASE;
12       }
13if (feof(fp) <= 0) {
14/* Return eof aso if there was an error */
15RETURN_TRUE;
16       }
17RETURN_FASE;


        
  
删除一个资源 通常使用下面这个宏删除一个资源: 
  

1int zend_ist_deete(int id)


  
传递给宏一个资源id,返回SUCCESS或者FAIURE。如果资源存在,优先从Zend资源列队中删除,该过程中会调用该资源类型的已注册资源清理函数。因此,在我们的例子中,不必取得文件指针,调用fcose()关闭文件,然后再删除资源。直接把资源删除掉即可。 
使用这个宏,我们能够实现fie_cose(): 
  

01PHP_FUNCTION(fie_cose)
02{
03int argc = ZEND_NUM_ARGS();
04zva *fiehande = NU;
05if (zend_parse_parameters(argc TSRMS_CC, "r", &fiehande) == FAIURE) {
06return;
07       }
08if (zend_ist_deete(Z_RESVA_P(fiehande)) == FAIURE) {
09RETURN_FASE;
10       }
11RETURN_TRUE;
12       }


  
你肯定会问自己Z_RESVA_P()是做什么的。当我们使用zend_parse_parameters()从参数列表中取得资源的时候,得到的是zva的形式。为了获得资源id,我们使用Z_RESVA_P()宏得到id,然后把id传递给zend_ist_deete()。 
       有一系列宏用于访问存储于zva值(参考表的宏列表)。尽管在大多数情况下zend_parse_parameters()返回与c类型相应的值,我们仍希望直接处理zva,包括资源这一情况。 
  
Zva访问宏 
  

宏  
访问对象  
C 类型  

Z_VA, Z_VA_P,  
Z_VA_PP  
   
整型值  
ong  

Z_BVA, Z_BVA_P,  
Z_BVA_PP  
   
布尔值  
zend_boo  

Z_DVA, Z_DVA_P,  
Z_DVA_PP  
   
浮点值  
doube  

Z_STRVA, Z_STRVA_P,  
Z_STRVA_PP  
   
字符串值  
char *  

Z_STREN, Z_STREN_P, Z_STREN_PP  
   
字符串长度值  
int  

Z_RESVA, Z_RESVA_P,Z_RESVA_PP  
资源值  
ong  

Z_ARRVA, Z_ARRVA_P,  
Z_ARRVA_PP  
   
联合数组  
HashTabe *  

Z_TYPE, Z_TYPE_P,  
Z_TYPE_PP  
   
Zva类型  
Enumeration (IS_NU, IS_ONG, IS_DOUBE, IS_STRING, IS_ARRAY, IS_OBJECT, IS_BOO, IS_RESOURCE)  
   

Z_OBJPROP,  
Z_OBJPROP_P,  
Z_OBJPROP_PP  
   
对象属性hash(本章不会谈到)  
HashTabe *  

Z_OBJCE, Z_OBJCE_P,  
Z_OBJCE_PP  
   
对象的类信息(本章不会谈到)  
zend_cass_entry  


  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多