mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-20 19:08:54 +00:00
144 lines
4.9 KiB
XML
144 lines
4.9 KiB
XML
![]() |
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||
|
<!-- $Revision: 1.1 $ -->
|
||
|
<sect1 id="zend.calling-user-functions">
|
||
|
<title>Calling User Functions</title>
|
||
|
<para>
|
||
|
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.
|
||
|
</para>
|
||
|
<para>
|
||
|
User functions can be called with the
|
||
|
function <function>call_user_function_ex</function>. 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.
|
||
|
</para>
|
||
|
<programlisting>
|
||
|
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);
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
Note that you don't have to specify both
|
||
|
<envar>function_table</envar> and <envar>object</envar>; either
|
||
|
will do. If you want to call a method, you have to supply the
|
||
|
object that contains this method, in which case
|
||
|
<function>call_user_function</function>automatically sets the
|
||
|
function table to this object's function table. Otherwise, you only
|
||
|
need to specify <envar>function_table</envar> and can set
|
||
|
<envar>object</envar> to <literal>NULL</literal>.
|
||
|
</para>
|
||
|
<para>
|
||
|
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
|
||
|
<literal>CG</literal>. To introduce the compiler globals to your
|
||
|
function, call the macro <literal>TSRMLS_FETCH</literal> once.
|
||
|
</para>
|
||
|
<para>
|
||
|
The function name is specified in a <envar>zval</envar>
|
||
|
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 <envar>zval</envar> containers again. Thus,
|
||
|
you only have to pass your arguments through to this function. This
|
||
|
<envar>zval</envar> must be of type <literal>IS_STRING</literal>.
|
||
|
</para>
|
||
|
<para>
|
||
|
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
|
||
|
<function>zval_dtor</function>) afterward!
|
||
|
</para>
|
||
|
<para>
|
||
|
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 <literal>0</literal>. If set to <literal>1</literal>, the
|
||
|
function consumes less memory but fails if any of the parameters
|
||
|
need separation.
|
||
|
</para>
|
||
|
<para>
|
||
|
<xref linkend='example.call-user-func'/> 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.
|
||
|
</para>
|
||
|
<example id='example.call-user-func'>
|
||
|
<title>Calling user functions.</title>
|
||
|
<programlisting>
|
||
|
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);
|
||
|
</programlisting>
|
||
|
</example>
|
||
|
<para/>
|
||
|
<programlisting>
|
||
|
<?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>");
|
||
|
?>
|
||
|
</programlisting>
|
||
|
<graphic fileref="figures/zend.10-userland.png"/>
|
||
|
</sect1>
|
||
|
<!-- Keep this comment at the end of the file
|
||
|
Local variables:
|
||
|
mode: sgml
|
||
|
sgml-omittag:t
|
||
|
sgml-shorttag:t
|
||
|
sgml-minimize-attributes:nil
|
||
|
sgml-always-quote-attributes:t
|
||
|
sgml-indent-step:1
|
||
|
sgml-indent-data:t
|
||
|
indent-tabs-mode:nil
|
||
|
sgml-parent-document:nil
|
||
|
sgml-default-dtd-file:"../../../manual.ced"
|
||
|
sgml-exposed-tags:nil
|
||
|
sgml-local-catalogs:nil
|
||
|
sgml-local-ecat-files:nil
|
||
|
End:
|
||
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
|
vim: et tw=78 syn=sgml
|
||
|
vi: ts=1 sw=1
|
||
|
-->
|