I'm starting to write a PHP extension and wish to just get my head around how to loop through an array that is passed (with the intention of changing the data value by value). Preferred method would be a for loop so that I can match array1 with array2 data e.g. array1[0] is linked to array2[0], [1] with [1] etc...
Anyone able to help?
modarray.c
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
extern zend_module_entry modarray_module_entry;
#define phpext_modarray_ptr &modarray_module_entry
PHP_FUNCTION(modarray);
static function_entry modarray_functions[] = {
PHP_FE(modarray, NULL)
PHP_FE_END
};
zend_module_entry modarray_module_entry = {
STANDARD_MODULE_HEADER,
"modarray",
modarray_functions,
NULL,
NULL,
NULL,
NULL,
NULL,
"0.1",
STANDARD_MODULE_PROPERTIES
};
ZEND_GET_MODULE(modarray)
PHP_FUNCTION(modarray)
{
zval *val, *val2;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &val, &val2) == FAILURE){
return;
}
SEPARATE_ZVAL(&val);
SEPARATE_ZVAL(&val2);
array_init(return_value);
zval_add_ref(&val);
zval_add_ref(&val2);
add_next_index_zval(return_value, val);
add_next_index_zval(return_value, val2);
}
PHP Code
<?php
$array1 = array(1,2,3,4);
$array2 = array(5,6,7,8);
echo '<pre>';
print_r(modarray($array1,$array2));
echo '</pre>';
?>
PHP Output
Array
(
[0] => Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
[1] => Array
(
[0] => 5
[1] => 6
[2] => 7
[3] => 8
)
)
There are two ways to do that, one fully "manual" by using the iteration API:
HashPosition pos;
zval *collection, **arg;
uint hash_key_type;
uint string_key_len;
ulong int_key;
char *string_key = NULL;
... get the collection from somewhere, e.g. argument parsing ...
while (!EG(exception) && zend_hash_get_current_data_ex(Z_ARRVAL_P(collection), (void **)&arg, &pos) == SUCCESS) {
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(collection), &pos);
MAKE_STD_ZVAL(key);
hash_key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(collection), &string_key, &string_key_len, &int_key, 0, &pos);
// Invoke e.g. zend_hash_update
zend_hash_move_forward_ex(Z_ARRVAL_P(collection), &pos);
}
The preferred alternative is to use on of three zend_hash_apply*()
functions with a callback which is considered more elegant:
static int replace_value(zval **arg, zval ****params TSRMLS_DC)
{
add_next_index_zval(params, val);
return ZEND_HASH_APPLY_REMOVE;
}
zval *in, ***out;
... fill in from somewhere from somewhere, e.g. argument parsing ...
array_init(**out);
zend_hash_apply_with_argument(Z_ARRVAL_P(collection, (apply_func_arg_t) replace_value, params TSRMLS_CC);
Note: I didn’t test either of the snippets locally but copied it from different places.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With