在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)轉載請註明出處;