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)