You can call user functions from your own modules, which is very
handy when implementing callbacks; for example, for array walking, searching, or
simply for event_based programs_
User functions can be called with the
function call_user_function_ex()_ It requires a hash value
for the function table you want to access, a pointer to an object (if you want
to call a method), the function name, return value, number of arguments,
argument array, and a flag indicating whether you want to perform zval separation_
ZEND_API int call_user_function_ex(HashTable *function_table, zval *object,
zval *function_name, zval **retval_ptr_ptr,
int param_count, zval **params[],
int no_separation); |
Note that you don't have to specify both
function_table and object; either
will do_ If you want to call a method, you have to supply the
object that contains this method, in which case
call_user_function()automatically sets the
function table to this object's function table_ Otherwise, you only
need to specify function_table and can set
object to NULL_
Usually, the default function table is the "root" function table
containing all function entries_ This function table is part of the
compiler globals and can be accessed using the macro
CG_ To introduce the compiler globals to your
function, call the macro TSRMLS_FETCH once_
The function name is specified in a zval
container_ This might be a bit surprising at first, but is quite a
logical step, since most of the time you'll accept function names
as parameters from calling functions within your script, which in
turn are contained in zval containers again_ Thus,
you only have to pass your arguments through to this function_ This
zval must be of type IS_STRING_
The next argument consists of a pointer to the return value_ You
don't have to allocate memory for this container; the function will
do so by itself_ However, you have to destroy this container (using
zval_dtor()) afterward!
Next is the parameter count as integer and an array containing all
necessary parameters_ The last argument specifies whether the
function should perform zval separation _ this should always be set
to 0_ If set to 1, the
function consumes less memory but fails if any of the parameters
need separation_
Ejemplo 38_1 shows a small demonstration of
calling a user function_ The code calls a function that's supplied
to it as argument and directly passes this function's return value
through as its own return value_ Note the use of the constructor
and destructor calls at the end _ it might not be necessary to do
it this way here (since they should be separate values, the
assignment might be safe), but this is bulletproof_
Ejemplo 38_1_ Calling user functions_ zval **function_name;
zval *retval;
if((ZEND_NUM_ARGS() != 1) || (zend_get_parameters_ex(1, &function_name) != SUCCESS))
{
WRONG_PARAM_COUNT;
}
if((*function_name)_>type != IS_STRING)
{
zend_error(E_ERROR, "Function requires string argument");
}
TSRMSLS_FETCH();
if(call_user_function_ex(CG(function_table), NULL, *function_name, &retval, 0, NULL, 0) != SUCCESS)
{
zend_error(E_ERROR, "Function call failed");
}
zend_printf("We have %i as type<br>", retval_>type);
*return_value = *retval;
zval_copy_ctor(return_value);
zval_ptr_dtor(&retval); |
|
<?php
dl("call_userland_so");
function test_function()
{
print("We are in the test function!<br>");
return("hello");
}
$return_value = call_userland("test_function");
print("Return value: \"$return_value\"<br>");
?> |
