Skip to content

Latest commit

 

History

History
176 lines (125 loc) · 6.18 KB

02.md

File metadata and controls

176 lines (125 loc) · 6.18 KB

参数传递

1,创建一个新的扩展

./ext_skel --extname=params

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

cd params
vi config.m4

3,编写代码

vi php_params.h
#注释掉下面的代码
//PHP_FUNCTION(confirm_params_compiled);

vi params.c
#添加下面的代码
ZEND_BEGIN_ARG_INFO(params_add_arginfo, 0)
	ZEND_ARG_INFO(0, a)
	ZEND_ARG_INFO(0, b)
ZEND_END_ARG_INFO()

static PHP_FUNCTION(params_add) {
	long a,b;
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &a, &b) == FAILURE) {
    	return;
	}
	RETURN_LONG(a+b);
}

4,解释

#define ZEND_FE_END            { NULL, NULL, NULL, 0, 0 }

//参数相关宏的定义 (Zend/zend_API.h)
#define ZEND_ARG_INFO(pass_by_ref, name)							{ #name, sizeof(#name)-1, NULL, 0, 0, 0, pass_by_ref},

#define ZEND_ARG_PASS_INFO(pass_by_ref)								{ NULL, 0, NULL, 0, 0, 0, pass_by_ref},

#define ZEND_ARG_OBJ_INFO(pass_by_ref, name, classname, allow_null) { #name, sizeof(#name)-1, #classname, sizeof(#classname)-1, IS_OBJECT, allow_null, pass_by_ref},

#define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, IS_ARRAY, allow_null, pass_by_ref},

#define ZEND_ARG_TYPE_INFO(pass_by_ref, name, type_hint, allow_null) { #name, sizeof(#name)-1, NULL, 0, type_hint, allow_null, pass_by_ref},

#define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args)	\
static const zend_arg_info name[] = {																		\
	{ NULL, 0, NULL, required_num_args, 0, return_reference, pass_rest_by_reference},
	
#define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference)	\
ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1)  

#define ZEND_END_ARG_INFO()		};

//宏说明
ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) //开始参数块定义,pass_rest_by_reference为1时,强制所有参数为引用类型
ZEND_END_ARG_INFO() //结束参数块定义
ZEND_ARG_INFO //声明普通参数,可以用来表示PHP中的int, float, double, string等基本数据类型
ZEND_ARG_OBJ_INFO //声明对象类型的参数
ZEND_ARG_ARRAY_INFO //声明数组类型的参数
ZEND_ARG_PASS_INFO(pass_by_ref)	 //pass_by_ref为1时,强制设置后续的参数为引用类型 

//展开3中ZEND_BEGIN_ARG_INFO语句
static const zend_arg_info params_add_arginfo[] = {
	{NULL, 0, NULL, -1, 0, ZEND_RETURN_VALUE, 0},
	{a, sizeof(a)-1, NULL, 0, 0, 0, 0},
	{b, sizeof(b)-1, NULL, 0, 0, 0, 0},
};

//参数在zend中的定义(Zend/zend_compile.h)
#define ZEND_RETURN_VALUE				0
#define ZEND_RETURN_REFERENCE			1
typedef struct _zend_arg_info {
	const char *name; //参数的名称
	zend_uint name_len; //参数名称的长度
	char *class_name; //当参数类型为类时,指定类的名称
	zend_uint class_name_len; //类名称的长度
	zend_uchar type_hint; 
	zend_bool allow_null; //是否允许设置为null
	zend_bool pass_by_reference; //是否设置为引用,即使用&操作符
}

#define PHP_FUNCTION			ZEND_FUNCTION //函数的实现
#define ZEND_FUNCTION(name)				ZEND_NAMED_FUNCTION(ZEND_FN(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

#define PHP_FE			ZEND_FE (php.h)//函数的定义,第一个参数是函数名,第二个参数是函数的参数的类型

(Zend/zend_API.h)
#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 }, 

5,更多的参数类型

#define Z_TYPE_P //获取参数类型 IS_NULL|IS_BOOL|IS_LONG|IS_DOUBLE|IS_STRING|IS_ARRAY|IS_RESOURCE|IS_OBJECT
#define Z_BVAL_P //获取bool类型参数的值
#define Z_LVAL_P //获取long类型参数的值
#define Z_DVAL_P //获取float类型参数的值
#define Z_STRVAL_P //获取string类型参数的值
#define Z_STRLEN_P //获取string类型参数的长度
#define Z_ARRVAL_P //获取array类型参数的值
#define Z_RESVAL_P //获取resource类型参数的值
#define Z_OBJCE_P //获取object类型参数的值

6,zend_parse_parameters的参数

//数据类型
Boolean 		b zend_bool      //布尔值
Long 			l long           //长整数
Double 			d double         //双精度浮点数
String 			s char *, int    //符串 (也可能是空字节)和其长度
Resource 		r zval*          // 资源, 保存在 zval*
Array 			a zval*          //数组, 保存在 zval*
Object 			o zval*          //任何类的)对象, 保存在 zval*
zval 			z zval*          //实际的 zval*
zval            O zval*         //由class entry 指定的类的)对象, 保存在 zval*
HashTable 		h HashTable*     //数组的哈希表
Function       f char *, int     //函数,方法名 (版本 > php5.1)
//操作符

|  -表明剩下的参数都是可选参数。如果用户没有传进来这些参数值,那么这些值就会被初始化成默认值。
/  -表明参数解析函数将会对剩下的参数以 SEPARATE_ZVAL_IF_NOT_REF() 的方式来提供这个参数的一份拷贝,除非这些参数是一个引用。
!  -表明剩下的参数允许被设定为 NULL(仅用在 a、o、O、r和z身上)。如果用户传进来了一个 NULL 值,则存储该参数的变量将会设置为 NULL。 

//字符串类型参数
ZEND_BEGIN_ARG_INFO(params_str_arginfo, 0)
	ZEND_ARG_INFO(0, a)
	ZEND_ARG_INFO(0, b)
ZEND_END_ARG_INFO()

static PHP_FUNCTION(params_str) {
	char *str = "";
	int str_len = 0;
	long i = 0;
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &str, &str_len, &i) == FAILURE) {
    	return;
	}

	php_printf("string(%d) value:", str_len);
	PHPWRITE(str, str_len);
	php_printf("\n");

	php_printf("int(%d)\n", i);
	php_printf("\n");
}	

//调用上面的方法
<?php
$func = "params_str";
call_user_func($func, "hello world", 10);//传递了完整的变量
call_user_func($func);//没有传递变量

//结果
string(11) value:hello world
int(10)

string(0) value:
int(0)