要在PHP扩展中处理数组类型参数,首先要了解以下ZEND API:
Z_TYPE_PP() //获取数据类型
zend_hash_internal_pointer_reset_ex();//初始化hash指针
zend_hash_get_current_data_ex() //获取当前hash存储值
zend_hash_move_forward_ex()//hahs指针移动至下一位
zend_hash_get_current_key_ex()//获取当前hash存储索引
array_init()//初始化哈希数组
add_assoc_zval_ex()//添加数组元素
现在有一个PHP扩展开发需求,要求开发一个函数,传入数组参数,将数组元素url编码后返回该数组。开发实例如下:
1.进入php源码包ext目录,运行命令
#./ext_skel --extname=mytools
2.进入mytools目录
修改config.m4文件,去掉dnl注释
PHP_ARG_ENABLE(mytools, whether to enable mytools support,
dnl Make sure that the comment is aligned:
[ --enable-mytools Enable mytools support])
3.修改php_mytools.h文件
加入PHP_FUNCTION(array_urlencode);
4.修改mytools.c文件
const zend_function_entry mytools_functions[] = {
PHP_FE(confirm_mytools_compiled, NULL)
PHP_FE(array_urlencode, NULL)
{NULL, NULL, NULL} /* Must be the last line in class_ext_functions[] */
};
尾部加入
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) {
char *key;
uint key_len;
ulong index;
HashPosition pos;
zval **data;
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;
}
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);
zval *nval;
ALLOC_ZVAL(nval);
MAKE_STD_ZVAL(nval);
ZVAL_STRING(nval, out_str , 1);
add_assoc_zval_ex(return_value, key, key_len, nval);
}
}else{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter is not array type");
return;
}
}
5.编译安装
/www/wdlinux/nginx_php-5.3.17/bin/phpize
./configure --with-php-config=/www/wdlinux/nginx_php-5.3.17/bin/php-config
make
make install
6.修改php.ini,,添加扩展
[mytools]
extension_dir=/www/wdlinux/nginx_php-5.3.17/lib/php/extensions/no-debug-non-zts-20090626
extension=mytools.so
7.重启nginx,测试
$arr = array('a'=>'http://www.google.com/?s=ssdd&t=32311#', 'b'=>'http://www.baidu.com/?s=ss dd');
var_dump(array_urlencode($arr));