用C/C++扩展你的PHP 为你的php增加功能(7)


PHP_FUNCTION(file_open){
char *filename = NULL;
char *mode = NULL;
int argc = ZEND_NUM_ARGS();
int filename_len;
int mode_len;
FILE *fp;
if (zend_parse_parameters(argc TSRMLS_CC, "ss", &filename,&filename_len, &mode, &mode_len) == FAILURE) {
return;
}
fp = VCWD_FOPEN(filename, mode);
if (fp == NULL) {
RETURN_FALSE;
}
ZEND_REGISTER_RESOURCE(return_value, fp, le_myfile);
}


你可能会注意到资源注册宏的第一个参数return_value,可此地找不到它的定义。这个变量自动的被扩展框架定义为zval * 类型的函数返回值。先前讨论的、能够影响返回值的RETURN_LONG() 和RETVAL_BOOL()宏确实改变了return_value的值。因此很容易猜到程序注册了我们取得的文件指针fp,同时设置return_value为该注册资源。

访问资源 需要使用下面的宏访问资源(参看表对宏参数的解释)

复制代码 代码如下:


ZEND_FETCH_RESOURCE(rsrc, rsrc_type, passed_id, default_id, resource_type_name, resource_type);


ZEND_FETCH_RESOURCE 宏参数
参数   含义  
rsrc   资源值保存到的变量名。它应该和资源有相同类型。  
rsrc_type   rsrc的类型,用于在内部把资源转换成正确的类型  
passed_id   寻找的资源值(例如zval **)  
default_id   如果该值不为-1,就使用这个id。用于实现资源的默认值。  
resource_type_name   资源的一个简短名称,用于错误信息。  
resource_type   注册资源的资源类型id  

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

复制代码 代码如下:


PHP_FUNCTION(file_eof){
int argc = ZEND_NUM_ARGS();
zval *filehandle = NULL;
FILE *fp;
if (zend_parse_parameters(argc TSRMLS_CC, "r", &filehandle) ==FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(fp, FILE *, &filehandle, -1, "standard-c-file",le_myfile);
if (fp == NULL){
RETURN_FALSE;
}
if (feof(fp) <= 0) {
/* Return eof also if there was an error */
RETURN_TRUE;
}
RETURN_FALSE;
}


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

复制代码 代码如下:


int zend_list_delete(int id)


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

复制代码 代码如下:


PHP_FUNCTION(file_close){
int argc = ZEND_NUM_ARGS();
zval *filehandle = NULL;
if (zend_parse_parameters(argc TSRMLS_CC, "r", &filehandle) == FAILURE) {
return;
}
if (zend_list_delete(Z_RESVAL_P(filehandle)) == FAILURE) {
RETURN_FALSE;
}
RETURN_TRUE;
}


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

Zval访问宏
  访问对象   C 类型  
Z_LVAL, Z_LVAL_P, Z_LVAL_PP   整型值   long  
Z_BVAL, Z_BVAL_P, Z_BVAL_PP   布尔值   zend_bool  
Z_DVAL, Z_DVAL_P, Z_DVAL_PP   浮点值   double  
Z_STRVAL, Z_STRVAL_P, Z_STRVAL_PP   字符串值   char *  
Z_STRLEN, Z_STRLEN_P, Z_STRLEN_PP   字符串长度值   int  
Z_RESVAL, Z_RESVAL_P,Z_RESVAL_PP   资源值   long  
Z_ARRVAL, Z_ARRVAL_P, Z_ARRVAL_PP   联合数组   HashTable *  
Z_TYPE, Z_TYPE_P, Z_TYPE_PP   Zval类型   Enumeration (IS_NULL, IS_LONG, IS_DOUBLE, IS_STRING, IS_ARRAY, IS_OBJECT, IS_BOOL, IS_RESOURCE)  
Z_OBJPROP, Z_OBJPROP_P, Z_OBJPROP_PP   对象属性hash(本章不会谈到) HashTable *  
Z_OBJCE, Z_OBJCE_P, Z_OBJCE_PP   对象的类信息   zend_class_entry  
用于访问zval值的宏

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/613d4dbed6d1c77df2df5be069ee1b62.html