Skip to content

Latest commit

 

History

History
414 lines (334 loc) · 14.3 KB

03.md

File metadata and controls

414 lines (334 loc) · 14.3 KB

返回值

1,创建一个新的扩展

./ext_skel --extname=return

2,修改config.m4,去掉没用的注释语句

cd return
vi config.m4

3,zend引擎在每个zif函数里定义了一个zval*类型的形参,名称为return_value,我们需要在函数里修改这个指针,函数执行完后内核将把这个指针指向的zval值返回

#define INTERNAL_FUNCTION_PARAMETERS int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC
//ht
//zval *return_value 返回值
//zval **return_value_ptr
//zval *this_ptr,如果此函数是一个类的方法,那么这个指针的含义和PHP语言中$this变量差不多。
//int return_value_used,代表用户端在调用此函数时有没有使用到它的返回值。

4,用于返回值的宏

a) RETURN_BOOL(0); //返回bool值

//宏的定义(Zend/zend_API.h)
#define RETURN_BOOL(b) 					{ RETVAL_BOOL(b); return; }
#define RETVAL_BOOL(b)					ZVAL_BOOL(return_value, b)//操作return_value
#define ZVAL_BOOL(z, b) do {		\
	zval *__z = (z);			\
	Z_LVAL_P(__z) = ((b) != 0);	\
	Z_TYPE_P(__z) = IS_BOOL;	\
} while (0)
//所以展开这个RETURN_BOOL(0),最终在函数里返回值的操作即是:
do {
	zval *__z = (return_value);
	Z_LVAL_P(__z) = ((0) != 0); //定义return_value值
	Z_TYPE_P(__z) = IS_BOOL; //定义return_value的类型
}while(0)

b) RETURN_STRING("hello world", 1); //返回字符串
//展开
do {
	const char *__s = ("hello world");
	zval *__z = return_value;
	Z_STRLEN_P(__z) = strlen(__s);//定义长度
	Z_STRVAL_P(__z) = (1?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);//定义值,estrndup函数实现字符串的复制
	Z_TYPE_P(__z) = IS_STRING;
}while(0)

c)RETURN_LONG(100); //返回long值
//展开
zval *__z = return_value;
Z_LVAL_P(__z) = 100;	
Z_TYPE_P(__z) = IS_LONG;

d)返回数组
array_init(return_value);//初始化return_value成数组,此操作完后就可以返回一个空的数组,$ret = array()




e)返回object
object_init(return_value);//初始化return_value成Object,此操作完成后返回一个空的对像


f)RETURN_RESOURCE(l);//返回resource
g)RETURN_NULL(); //return null;
h)RETURN_EMPTY_STRING(); //return "";
i)RETURN_ZVAL;
j)RETURN_FALSE; //return false;
k)RETURN_TRUE//return true;

#define RETVAL_RESOURCE(l)				ZVAL_RESOURCE(return_value, l) //付值resource变量到系统返回值(return_value)
#define RETVAL_BOOL(b)					ZVAL_BOOL(return_value, b) //付值bool变量到系统返回值(return_value)
#define RETVAL_NULL() 					ZVAL_NULL(return_value) //付值NULL到系统返回值(return_value)
#define RETVAL_LONG(l) 					ZVAL_LONG(return_value, l) //付值long变量到系统返回值(return_value)
#define RETVAL_DOUBLE(d) 				ZVAL_DOUBLE(return_value, d) //付值double变量到系统返回值(return_value)
#define RETVAL_STRING(s, duplicate) 		ZVAL_STRING(return_value, s, duplicate) //付值string变量到系统返回值(return_value)
#define RETVAL_STRINGL(s, l, duplicate) 	ZVAL_STRINGL(return_value, s, l, duplicate)
#define RETVAL_EMPTY_STRING() 			ZVAL_EMPTY_STRING(return_value) //返回empty string
#define RETVAL_ZVAL(zv, copy, dtor)		ZVAL_ZVAL(return_value, zv, copy, dtor)//返回zval变量
#define RETVAL_FALSE  					ZVAL_BOOL(return_value, 0) //返回false
#define RETVAL_TRUE   					ZVAL_BOOL(return_value, 1) //返回true


#define RETURN_RESOURCE(l) 				{ RETVAL_RESOURCE(l); return; }
#define RETURN_BOOL(b) 					{ RETVAL_BOOL(b); return; }
#define RETURN_NULL() 					{ RETVAL_NULL(); return;}
#define RETURN_LONG(l) 					{ RETVAL_LONG(l); return; }
#define RETURN_DOUBLE(d) 				{ RETVAL_DOUBLE(d); return; }
#define RETURN_STRING(s, duplicate) 	{ RETVAL_STRING(s, duplicate); return; }
#define RETURN_STRINGL(s, l, duplicate) { RETVAL_STRINGL(s, l, duplicate); return; }
#define RETURN_EMPTY_STRING() 			{ RETVAL_EMPTY_STRING(); return; }
#define RETURN_ZVAL(zv, copy, dtor)		{ RETVAL_ZVAL(zv, copy, dtor); return; }
#define RETURN_FALSE  					{ RETVAL_FALSE; return; }
#define RETURN_TRUE   					{ RETVAL_TRUE; return; }

5,数组函数

1)Zend's API for Associative Arrays

zval *arr;
MAKE_STD_ZVAL(arr);

array_init(arr); //$arr = array();
add_assoc_long(arr, "a", 10); //$arr["a"] = 10; 
add_asoc_unset(arr, "a"); //unset(arr["a"]);
add_assoc_bool(arr, "b", 1); //$arr["b"] = true;
add_assoc_resource(arr, "c", 10); //$arr["c"] = $resource;
add_assoc_double(arr, "d", 2.15); //$arr["d"] = 2.15;
add_assoc_string(arr, "e", "hello", 1); //$arr["e"] = "hello";最后一个参数表示字符串值是否复制
add_assoc_stringl();

zval *sub;
MAKE_STD_ZVAL(sub);
array_init(sub);
add_assoc_zval(arr, "f", sub); //$arr["f"] = $sub;

2)Zend's API for Indexed Arrays, Part 1

zval *arr;
MAKE_STD_ZVAL(arr);

array_init(arr); //$arr = array();
add_index_long(arr, 1, 10); //$arr[1] = 10;
add_index_unset(arr, 1); //unset($arr[1]);
add_index_bool(arr, 2, 1); //$arr[2] = true;
add_index_resource(arr, 3, 10); //$arr[3] = $resource;
add_index_double(arr, 4, 2.15); //$arr[4] = 2.15;
add_index_string(arr, 5, "hello", 1); //$arr[5] = "hello";最后一个参数表示字符串值是否复制
add_index_stringl();

zval *sub;
MAKE_STD_ZVAL(sub);
array_init(sub);
add_index_zval(arr, 6, sub); //$arr[6] = $sub;

3)Zend's API for Indexed Arrays, Part 2

zval *arr;
MAKE_STD_ZVAL(arr);

array_init(arr); //$arr = array();
add_next_index_long(arr, 10); //$arr[] = 10;
add_next_index_unset(arr); //unset($arr[]);
add_next_index_bool(arr, 1); //$arr[] = true;
add_next_index_resource(arr, 10); //$arr[] = $resource;
add_next_index_double(arr, 2.15); //$arr[] = 2.15;
add_next_index_string(arr, "hello", 1); //$arr[] = "hello";最后一个参数表示字符串值是否复制
add_next_index_stringl();

zval *sub;
MAKE_STD_ZVAL(sub);
array_init(sub);
add_next_index_zval(arr, sub); //$arr[] = $sub;

6,Object函数

zval *obj;
MAKE_STD_ZVAL(obj);

object_init(obj);//$obj = new stdClass;
add_property_long(obj, "a", 10); //$obj->a = 10;
add_property_unset(obj, "a"); //unset($obj->a);
add_property_bool(obj, "b", 1); //$obj->b = true;
add_property_resource(obj, "c", 10); //$obj->c = $resource;
add_property_double(obj, "d", 2.15); //$obj->d = 2.15;
add_property_string(obj, "e", "hello", 1);//$obj->e = "hello"; 最后一个参数表示字符串值是否复制
add_property_stringl();

zval *sub;
MAKE_STD_ZVAL(sub);
object_init(sub); //$sub  = new stdClass;

add_property_zval(obj, "f", sub); //$obj->f = $sub;

7,Zval

struct _zend_object_handlers {
	/* general object functions */
	zend_object_add_ref_t					add_ref;
	zend_object_del_ref_t					del_ref;
	zend_object_clone_obj_t					clone_obj;
	/* individual object functions */
	zend_object_read_property_t				read_property;
	zend_object_write_property_t			write_property;
	zend_object_read_dimension_t			read_dimension;
	zend_object_write_dimension_t			write_dimension;
	zend_object_get_property_ptr_ptr_t		get_property_ptr_ptr;
	zend_object_get_t						get;
	zend_object_set_t						set;
	zend_object_has_property_t				has_property;
	zend_object_unset_property_t			unset_property;
	zend_object_has_dimension_t				has_dimension;
	zend_object_unset_dimension_t			unset_dimension;
	zend_object_get_properties_t			get_properties;
	zend_object_get_method_t				get_method;
	zend_object_call_method_t				call_method;
	zend_object_get_constructor_t			get_constructor;
	zend_object_get_class_entry_t			get_class_entry;
	zend_object_get_class_name_t			get_class_name;
	zend_object_compare_t					compare_objects;
	zend_object_cast_t						cast_object;
	zend_object_count_elements_t			count_elements;
	zend_object_get_debug_info_t			get_debug_info;
	zend_object_get_closure_t				get_closure;
	zend_object_get_gc_t					get_gc;
};

typedef struct _zend_object_value {
	zend_object_handle handle;
	const zend_object_handlers *handlers;
} zend_object_value;

typedef union _zvalue_value {
	long lval;					/* long value */
	double dval;				/* double value */
	struct {
		char *val;
		int len;
	} str;						/* string value */
	HashTable *ht;				/* hash table value */
	zend_object_value obj;		/* object value */
} zvalue_value;

struct _zval_struct {
	/* Variable information */
	zvalue_value value;				/* 值 */
	zend_uint refcount__gc;			/* 引用计数 */
	zend_uchar type;				/* 变量类型 */
	zend_uchar is_ref__gc;			/* 是否引用变量, &$a */
};

#define ZVAL_FALSE(z)  					ZVAL_BOOL(z, 0) //设置zval
#define ZVAL_TRUE(z)  					ZVAL_BOOL(z, 1)

/* struct操作宏 */
#define Z_LVAL(zval)    (zval).value.lval  //获取long值
#define Z_BVAL(zval)	((zend_bool)(zval).value.lval)  //获取bool值
#define Z_DVAL(zval)	(zval).value.dval //获取double值
#define Z_STRVAL(zval)	(zval).value.str.val //获取string的指针
#define Z_STRLEN(zval)	 (zval).value.str.len //获取string的长度
#define Z_ARRVAL(zval)	(zval).value.ht       //获取hashtable值
#define Z_OBJVAL(zval)	(zval).value.obj      //获取object值
#define Z_OBJ_HANDLE(zval)	Z_OBJVAL(zval).handle //
#define Z_OBJ_HT(zval)		Z_OBJVAL(zval).handlers //
#define Z_OBJCE(zval)		zend_get_class_entry(&(zval) TSRMLS_CC) //
#define Z_OBJPROP(zval)		Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) //
#define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf //
#define Z_RESVAL(zval)		(zval).value.lval //获取long值
#define Z_OBJDEBUG(zval,is_tmp)	(Z_OBJ_HANDLER((zval),get_debug_info)?Z_OBJ_HANDLER((zval),get_debug_info)(&(zval),&is_tmp TSRMLS_CC):(is_tmp=0,Z_OBJ_HANDLER((zval),get_properties)?Z_OBJPROP(zval):NULL)) //

/* 指针操作宏 */
#define Z_LVAL_P(zval_p)		Z_LVAL(*zval_p)
#define Z_BVAL_P(zval_p)		Z_BVAL(*zval_p)
#define Z_DVAL_P(zval_p)		Z_DVAL(*zval_p)
#define Z_STRVAL_P(zval_p)		Z_STRVAL(*zval_p)
#define Z_STRLEN_P(zval_p)		Z_STRLEN(*zval_p)
#define Z_ARRVAL_P(zval_p)		Z_ARRVAL(*zval_p)
#define Z_OBJPROP_P(zval_p)		Z_OBJPROP(*zval_p)
#define Z_OBJCE_P(zval_p)		Z_OBJCE(*zval_p)
#define Z_RESVAL_P(zval_p)		Z_RESVAL(*zval_p)
#define Z_OBJVAL_P(zval_p)		Z_OBJVAL(*zval_p)
#define Z_OBJ_HANDLE_P(zval_p)	Z_OBJ_HANDLE(*zval_p)
#define Z_OBJ_HT_P(zval_p)		Z_OBJ_HT(*zval_p)
#define Z_OBJ_HANDLER_P(zval_p, h)	Z_OBJ_HANDLER(*zval_p, h)	#define Z_OBJDEBUG_P(zval_p,is_tmp)	Z_OBJDEBUG(*zval_p,is_tmp)

/*  */
#define Z_LVAL_PP(zval_pp)		Z_LVAL(**zval_pp)
#define Z_BVAL_PP(zval_pp)		Z_BVAL(**zval_pp)
#define Z_DVAL_PP(zval_pp)		Z_DVAL(**zval_pp)
#define Z_STRVAL_PP(zval_pp)	Z_STRVAL(**zval_pp)
#define Z_STRLEN_PP(zval_pp)	Z_STRLEN(**zval_pp)
#define Z_ARRVAL_PP(zval_pp)	Z_ARRVAL(**zval_pp)
#define Z_OBJPROP_PP(zval_pp)	Z_OBJPROP(**zval_pp)
#define Z_OBJCE_PP(zval_pp)		Z_OBJCE(**zval_pp)
#define Z_RESVAL_PP(zval_pp)	Z_RESVAL(**zval_pp)
#define Z_OBJVAL_PP(zval_pp)	Z_OBJVAL(**zval_pp)
#define Z_OBJ_HANDLE_PP(zval_p)	Z_OBJ_HANDLE(**zval_p)
#define Z_OBJ_HT_PP(zval_p)		Z_OBJ_HT(**zval_p)
#define Z_OBJ_HANDLER_PP(zval_p, h)		Z_OBJ_HANDLER(**zval_p, h)
#define Z_OBJDEBUG_PP(zval_pp,is_tmp)	Z_OBJDEBUG(**zval_pp,is_tmp)


/* 获取zval的变量类型 */
#define Z_TYPE(zval)		(zval).type
#define Z_TYPE_P(zval_p)	Z_TYPE(*zval_p)
#define Z_TYPE_PP(zval_pp)	Z_TYPE(**zval_pp)

/* zval初始化宏 */
#define ALLOC_ZVAL(z)	(z) = (zval *) emalloc(sizeof(zval)) //初始化zval,分配内存
#define FREE_ZVAL(z)	efree_rel(z)  //释放zvalue内存

#define ALLOC_ZVAL_REL(z)(z) = (zval *) emalloc_rel(sizeof(zval))
#define FREE_ZVAL_REL(z)	efree_rel(z)

/* HashTable初始化宏 */
#define ALLOC_HASHTABLE(ht)	 (ht) = (HashTable *) emalloc(sizeof(HashTable)) //初始化HashTable
#define FREE_HASHTABLE(ht)	efree(ht)

#define ALLOC_HASHTABLE_REL(ht)	 (ht) = (HashTable *) emalloc_rel(sizeof(HashTable))
#define FREE_HASHTABLE_REL(ht)	efree_rel(ht)


#define INIT_PZVAL(z) (z)->refcount__gc = 1; (z)->is_ref__gc = 0; //设置refcount
#define INIT_ZVAL(z) z = zval_used_for_init;

#define ALLOC_INIT_ZVAL(zp)	 ALLOC_ZVAL(zp); INIT_ZVAL(*zp); //分配内存并设置默认值
#define MAKE_STD_ZVAL(zv)	ALLOC_ZVAL(zv); INIT_PZVAL(zv); //分配内存并设置默认值
#define PZVAL_IS_REF(z)		Z_ISREF_P(z)

/* 拷贝zval的值 */
#define ZVAL_COPY_VALUE(z, v)					\
do {										\
	(z)->value = (v)->value;				\
	Z_TYPE_P(z) = Z_TYPE_P(v);				\
} while (0)


#define INIT_PZVAL_COPY(z, v)					\
do {										\
	ZVAL_COPY_VALUE(z, v);					\
	Z_SET_REFCOUNT_P(z, 1);					\
	Z_UNSET_ISREF_P(z);						\
} while (0)




#define ZVAL_IS_NULL(z) (Z_TYPE_P(z)==IS_NULL) //判断zval是否为NULL

/* 设置zval为resource类型值 */
#define ZVAL_RESOURCE(z, l) do {	\
	zval *__z = (z);			\
	Z_LVAL_P(__z) = l;			\
	Z_TYPE_P(__z) = IS_RESOURCE;\
} while (0)

/* 设置zval为bool类型值 */
#define ZVAL_BOOL(z, b) do {		\
	zval *__z = (z);			\
	Z_LVAL_P(__z) = ((b) != 0);	\
	Z_TYPE_P(__z) = IS_BOOL;	\
} while (0)

/* 设置zval为NULL */
#define ZVAL_NULL(z) {				\
	Z_TYPE_P(z) = IS_NULL;		\
}

/* 设置zval为long值 */
#define ZVAL_LONG(z, l) {			\
	zval *__z = (z);			\
	Z_LVAL_P(__z) = l;			\
	Z_TYPE_P(__z) = IS_LONG;	\
}

/* 设置zval为double值 */
#define ZVAL_DOUBLE(z, d) {			\
	zval *__z = (z);			\
	Z_DVAL_P(__z) = d;			\
	Z_TYPE_P(__z) = IS_DOUBLE;	\
}

/* 设置zval为string值 */
#define ZVAL_STRING(z, s, duplicate) do {	\
	const char *__s=(s);				\
	zval *__z = (z);					\
	Z_STRLEN_P(__z) = strlen(__s);		\
	Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\
	Z_TYPE_P(__z) = IS_STRING;			\
} while (0)

/* 设置zval为string值 */
#define ZVAL_STRINGL(z, s, l, duplicate) do {	\
	const char *__s=(s); int __l=l;			\
	zval *__z = (z);						\
	Z_STRLEN_P(__z) = __l;					\
	Z_STRVAL_P(__z) = (duplicate?estrndup(__s, __l):(char*)__s);\
	Z_TYPE_P(__z) = IS_STRING;				\
} while (0)

/* 设置zval为empty string值 */
#define ZVAL_EMPTY_STRING(z) do {	\
	zval *__z = (z);			\
	Z_STRLEN_P(__z) = 0;		\
	Z_STRVAL_P(__z) = STR_EMPTY_ALLOC();\
	Z_TYPE_P(__z) = IS_STRING;	\
} while (0)

/* 设置zval为zval值 */
#define ZVAL_ZVAL(z, zv, copy, dtor) {			\
	zend_uchar is_ref = Z_ISREF_P(z);		\
	zend_uint refcount = Z_REFCOUNT_P(z);	\
	ZVAL_COPY_VALUE(z, zv);					\
	if (copy) {								\
		zval_copy_ctor(z);					\
    }										\
	if (dtor) {								\
		if (!copy) {						\
			ZVAL_NULL(zv);					\
		}									\
		zval_ptr_dtor(&zv);					\
    }										\
	Z_SET_ISREF_TO_P(z, is_ref);			\
	Z_SET_REFCOUNT_P(z, refcount);			\
}