When exchanging data from your own extensions with PHP
scripts, one of the most important issues is the creation of
variables. This section shows you how to deal with the
variable types that PHP supports.
To create new variables that can be seen "from the
outside" by the executing script, you need to allocate a
new zval container, fill this
container with meaningful values, and then introduce it to
Zend's internal symbol table. This basic process is common
to all variable creations:
zval *new_variable; /* allocate and initialize new container */ MAKE_STD_ZVAL(new_variable); /* set type and variable contents here, see the following sections */ /* introduce this variable by the name "new_variable_name" into the symbol table */ ZEND_SET_SYMBOL(EG(active_symbol_table), "new_variable_name", new_variable); /* the variable is now accessible to the script by using $new_variable_name */ |
The macro MAKE_STD_ZVAL
allocates a new zval container using
ALLOC_ZVAL and initializes it
using INIT_ZVAL. As implemented in
Zend at the time of this writing, initializing means setting the
reference count to 1 and clearing
the is_ref flag, but this process
could be extended later - this is why it's a good idea to
keep using MAKE_STD_ZVAL instead
of only using ALLOC_ZVAL. If you
want to optimize for speed (and you don't have to
explicitly initialize the zval
container here), you can use
ALLOC_ZVAL, but this isn't recommended because it
doesn't ensure data integrity.
ZEND_SET_SYMBOL takes care of
introducing the new variable to Zend's symbol table. This
macro checks whether the value already exists in the symbol
table and converts the new symbol to a reference if so
(with automatic deallocation of the old
zval container). This is the preferred method if speed
is not a crucial issue and you'd like to keep memory usage
low.
Note that ZEND_SET_SYMBOL
makes use of the Zend executor globals via the macro EG. By specifying
EG(active_symbol_table), you get access to the
currently active symbol table, dealing with the active,
local scope. The local scope may differ depending on
whether the function was invoked from within a
function.
If you need to optimize for speed and don't care about
optimal memory usage, you can omit the check for an
existing variable with the same value and instead force
insertion into the symbol table by using zend_hash_update():
zval *new_variable; /* allocate and initialize new container */ MAKE_STD_ZVAL(new_variable); /* set type and variable contents here, see the following sections */ /* introduce this variable by the name "new_variable_name" into the symbol table */ zend_hash_update( EG(active_symbol_table), "new_variable_name", strlen("new_variable_name") + 1, new_variable, sizeof(zval *), NULL ); |
The variables generated with the snippet above will
always be of local scope, so they reside in the context in
which the function has been called. To create new variables
in the global scope, use the same method but refer to
another symbol table:
zval *new_variable; // allocate and initialize new container MAKE_STD_ZVAL(new_variable); // // set type and variable contents here // // introduce this variable by the name "new_variable_name" into the global symbol table ZEND_SET_SYMBOL( EG(symbol_table), "new_variable_name", new_variable); |
Note: The
active_symbol_table variable is a pointer, but symbol_table is not. This is why you
have to use
EG(active_symbol_table) and
EG(symbol_table) as parameters to ZEND_SET_SYMBOL - it requires a pointer.
Similarly, to get a more efficient version, you can
hardcode the symbol table update:
zval *new_variable; // allocate and initialize new container MAKE_STD_ZVAL(new_variable); // // set type and variable contents here // // introduce this variable by the name "new_variable_name" into the global symbol table zend_hash_update( EG(symbol_table), "new_variable_name", strlen("new_variable_name") + 1, new_variable, sizeof(zval *), NULL ); |
Note: You can see that the global variable is actually
not accessible from within the function. This is because
it's not imported into the local scope using global $global_variable; in the PHP
source.