在zend_API.h中的定义如下,很直观了
ZEND_API void wrong_param_count(void);
#define WRONG_PARAM_COUNT { wrong_param_count(); return; }
2, 取得参数
-
l - 长整形
-
d - 双精度浮点类型
-
s - 字符串 (也可能是空字节)和其长度
-
b - 布尔型
-
r - 资源, 保存在 zval*
-
a - 数组, 保存在zval*
-
o - (任何类的)对象, 保存在 zval *
-
O - (由class entry 指定的类的)对象, 保存在 zval *
-
z - 实际的 zval*
-
下面的一些字符在类型说明字符串(就是那个char *type_spec)中具有特别的含义:
| - 表明后面的参数都是可选参数。如果用户没有传进来这些参数值,那么这些值就会被初始化成默认值。
/ - 表明前面的参数会被参数解析函数应用 SEPARATE_ZVAL_IF_NOT_REF() 方式来提供这个参数的一份拷贝,除非这些参数是一个引用。
! - 表明前面的参数允许被设定为 NULL(仅用在 a、o、O、r和z身上)。如果传进来了一个 NULL 值,则存储该参数的变量将会设置为 NULL。
来看个例子 :
/* 取得一个长整型,一个字符串和它的长度,再取得一个 zval 值。 */
long l;
char *s;
int s_len;
zval *param;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"lsz", &l, &s, &s_len, ¶m) == FAILURE) {
return;
}
在我的扩展中,我使用了zend_get_parameters_ex() , 它将所有取回的参数都放在一个zval**(后面会讲)的结构中;
zval ** z_array;
if(FAILURE = zend_get_parameters_ex(1, &z_array){
RETURN_BOOL(0);}
而后,你就可以很控制函数对参数进行解析进行控制; 这也是我为什么选用这个的原因之一 :)
3,核心的核心,zval;
先来看看 zval的定义:
typedef pval zval;
typedef struct _zval_struct zval;
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct {
char *val;
int len;
} str;
HashTable *ht; /* hash table value */
struct {
zend_class_entry *ce;
HashTable *properties;
} obj;
} zvalue_value;
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
unsigned char type; /* active type */
unsigned char is_ref;
short refcount;
};
可以看出, zval中的 value是个联合体,显然它是用来容纳各种类型的值的, 相应的有个type来指明值的类型,is_ref 和 refcount是用来指明是否是引用和,引用计数的;
好到这一步,我们已经将参数的"值"取来了,现在的问题就是让它变成C++中的值(有类型);
我写的一段数组解析代码:
std::map<string, string> photo;
convert_to_array_ex(z_array);
count = zend_hash_num_elements(Z_ARRVAL_PP(z_array));
zend_hash_internal_pointer_reset(Z_ARRVAL_PP(z_array));
for (i = 0; i < count; i ++)
{
char* key;
unsigned long idx;
if (zend_hash_get_current_key(Z_ARRVAL_PP(z_array), &key, &idx, 0) == HASH_KEY_IS_STRING)
{
zend_hash_get_current_data(Z_ARRVAL_PP(z_array), (void**) &z_item);
convert_to_string_ex(z_item);
photo.insert(pair<string, string>(string(key), string(Z_STRVAL_PP(z_item))));
}
zend_hash_move_forward(Z_ARRVAL_PP(z_array));
}
今天就写这么多,改天有时间,再补。
更多内容, 可以参看 yAnbiN 的 深入 PHP 内核
做个广告,呵呵,也可以参看由我们牛X的战友Ranix翻译的Programming PHP的Extending PHP一章
//By:惠新宸 (xinchen.hui(at)alibaba-inc.com)转载请注明出处;