Dealing with Arguments Passed by Reference
If your function accepts arguments passed by reference that you
intend to modify, you need to take some precautions_
What we didn't say yet is that under the circumstances presented so
far, you don't have write access to any zval containers
designating function parameters that have been passed to you_ Of course, you
can change any zval containers that you created within
your function, but you mustn't change any zvals that refer to
Zend_internal data!
We've only discussed the so_called *_ex() API
so far_ You may have noticed that the API functions we've used are
called zend_get_parameters_ex() instead of
zend_get_parameters(),
convert_to_long_ex() instead of
convert_to_long(), etc_ The
*_ex() functions form the so_called new
"extended" Zend API_ They give a minor speed increase over the old
API, but as a tradeoff are only meant for providing read_only
access_
Because Zend works internally with references, different variables
may reference the same value_ Write access to a
zval container requires this container to contain
an isolated value, meaning a value that's not referenced by any
other containers_ If a zval container were
referenced by other containers and you changed the referenced
zval, you would automatically change the contents
of the other containers referencing this zval
(because they'd simply point to the changed value and thus change
their own value as well)_
zend_get_parameters_ex() doesn't care about
this situation, but simply returns a pointer to the desired
zval containers, whether they consist of references
or not_ Its corresponding function in the traditional API,
zend_get_parameters(), immediately checks for
referenced values_ If it finds a reference, it creates a new,
isolated zval container; copies the referenced data
into this newly allocated space; and then returns a pointer to the
new, isolated value_
This action is called zval separation
(or pval separation)_ Because the *_ex() API
doesn't perform zval separation, it's considerably faster, while
at the same time disabling write access_
To change parameters, however, write access is required_ Zend deals
with this situation in a special way: Whenever a parameter to a function is
passed by reference, it performs automatic zval separation_ This means that
whenever you're calling a function like
this in PHP, Zend will automatically ensure
that $parameter is being passed as an isolated value, rendering it
to a write_safe state:
my_function(&$parameter); |
But this is not the case with regular parameters!
All other parameters that are not passed by reference are in a read_only
state_
This requires you to make sure that you're really working with a
reference _ otherwise you might produce unwanted results_ To check for a
parameter being passed by reference, you can use the macro
PZVAL_IS_REF_ This macro accepts a zval*
to check if it is a reference or not_ Examples are given in
in Ejemplo 32_3_
Ejemplo 32_3_ Testing for referenced parameter passing_ zval *parameter;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", ¶meter) == FAILURE)
return;
/* check for parameter being passed by reference */
if (!PZVAL_IS_REF(*parameter)) {
{
zend_error(E_WARNING, "Parameter wasn't passed by reference");
RETURN_NULL();
}
/* make changes to the parameter */
ZVAL_LONG(*parameter, 10); |

|