上篇文章主要介绍了一维数组的处理方法,使用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