上篇文章主要介绍了一维数组的处理方法,使用ZEND API结合递归算法遍历处理多维数组也不是什么难事。处理多维数组首先要了解一下ZEND API:
MAKE_STD_ZVAL();//注册zval变量
SEPARATE_ZVAL_IF_NOT_REF()//如果没有分支则分离变量
add_assoc_string_ex//添加字符串数组元素
现需要开发一个PHP扩展,将多维数组元素url编码然后返回。修改mytools.c文件,添加函数(流程请参照上篇文章:php扩展开发-数组处理(一),这里不再赘述)。
static void php_array_urlencode(zval **array_input, zval *return_value, char *childkey TSRMLS_CC){
char *key;
uint key_len;
ulong index;
HashPosition pos;
zval **data;
zval *childvalue;
MAKE_STD_ZVAL(childvalue);
array_init(childvalue);
for (
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(array_input), &pos);
zend_hash_get_current_data_ex(Z_ARRVAL_PP(array_input), (void **) &data, &pos) == SUCCESS;
zend_hash_move_forward_ex(Z_ARRVAL_PP(array_input), &pos)
) {
if (zend_hash_get_current_key_ex(Z_ARRVAL_PP(array_input), &key, &key_len, &index, 0, &pos) != HASH_KEY_IS_STRING) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Numeric keys are not allowed in the definition array");
zval_dtor(return_value);
RETURN_FALSE;
}
if (Z_ARRVAL_PP(data)->nApplyCount > 1) {
return;
}
if (Z_TYPE_PP(data) == IS_ARRAY) {
SEPARATE_ZVAL_IF_NOT_REF(data);
Z_ARRVAL_PP(data)->nApplyCount++;
php_array_urlencode(data, return_value, key TSRMLS_CC);
Z_ARRVAL_PP(data)->nApplyCount--;
}else{
SEPARATE_ZVAL(data);
if (Z_TYPE_PP(data) == IS_OBJECT) {
zend_class_entry *ce;
ce = Z_OBJCE_PP(data);
if (!ce->__tostring) {
ZVAL_FALSE(*data);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array's value contain object and can not be converted to string ");
return;
}
}
convert_to_string(*data);
char *out_str;
int str_len = strlen(Z_STRVAL_PP(data));
int out_str_len;
out_str = php_url_encode((const char*)(Z_STRVAL_PP(data)), str_len, &out_str_len);
if(childkey != NULL){
add_assoc_string_ex(childvalue, key, key_len, out_str, 1);
}else{
add_assoc_string_ex(return_value, key, key_len, out_str, 1);
}
}
}
childkey != NULL && add_assoc_zval_ex(return_value, childkey, strlen(childkey)+1, childvalue);
}
修改PHP_FUNCTION(array_urlencode)
PHP_FUNCTION(array_urlencode)
{
zval **array_input;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &array_input) == FAILURE){
return;
}
SEPARATE_ZVAL(array_input);
if (Z_TYPE_PP(array_input) == IS_ARRAY) {
array_init(return_value);
php_array_urlencode(array_input, return_value, NULL TSRMLS_CC);
}else{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter is not array type");
return;
}
}
处理多维数组和一位数组的原理一样,主要是遍历数组元素,处理后按原来的数据结构返回。在循环遍历数组的时候zend
HashTable结构体中nApplyCount成员作为访问标志,防止对同一个HashTable同时进行多次遍历
。每次进入遍历函数时将nApplyCount值加1,退出遍历函数时将nApplyCount值减1。开始遍历之前如果发现nApplyCount > 3就直接报告错误信息并退出遍历。
如果您要转载此文章请注明出处:http://my.oschina.net/u/554660/blog/169630