Data Retrieval

In order to retrieve a variable from userspace, you'll need to look in whatever symbol table it's stored in. The following code segment shows using the zend_hash_find() function for this purpose:

 zval **fooval;

 if (zend_hash_find(EG(active_symbol_table),
 "foo", sizeof("foo"),
 (void**)&fooval) == SUCCESS) {
 php_printf("Got the value of $foo!");
 } else {
 php_printf("$foo is not defined.");

A few parts of this example should look a little funny. Why is fooval defined to two levels of indirection? Why is sizeof() used for determining the length of "foo"? Why is &fooval, which would evaluate to a zval***, cast to a void**? If you asked yourself all three of these questions, pat yourself on the back.

First, it's worth knowing that HashTables aren't only used for userspace variables. The HashTable structure is so versatile that it's used all over the engine and in some cases it makes perfect sense to want to store a non-pointer value. A HashTable bucket is a fixed size, however, so in order to store data of any size, a HashTable will allocate a block of memory to wrap the data being stored. In the case of variables, it's a zval* being stored, so the HashTable storage mechanism allocates a block of memory big enough to hold a pointer. The HashTable's bucket uses that new pointer to carry around the zval* and you effectively wind up with a zval** inside the HashTable. The reason for storing a zval* when HashTables are clearly capable of storing a full zval will be covered in the next chapter.

When trying to retrieve that data, the HashTable only knows that it has a pointer to something. In order to populate that pointer into a calling function's local storage, the calling function will naturally dereference the local pointer, resulting in a variable of indeterminate type with two levels of indirection (such as void**). Knowing that your "indeterminate type" in this case is zval*, you can see where the type being passed into zend_hash_find() will look different to the compiler, having three levels of indirection rather than two. This is done on purpose here so a simple typecast is added to the function call to silence compiler warnings.

The reason sizeof() was used in the previous example was to include the terminating NULL in the "foo" constant used for the variable's label. Using 4 here would have worked equally well; however, it is discouraged because changes to the label name may affect its length, and it's much easier to find places where the length is hard-coded if it contains the label text that's being replaced anyway. (strlen("foo")+1) could have also solved this problem; however, some compilers do not optimize this step and the resulting binary might end up performing a pointless string length loopwhat would be the fun in that?

If zend_hash_find() locates the item you're looking for, it populates the dereferenced pointer provided with the address of the bucket pointer it allocated when the requested data was first added to the HashTable and returns an integer value matching the SUCCESS constant. If zend_hash_find() cannot locate the data, it leaves the pointer untouched and returns an integer value matching the FAILURE constant.

In the case of userspace variables stored in a symbol table, SUCCESS or FAILURE effectively means that the variable is or is not set.

The PHP Life Cycle

Variables from the Inside Out

Memory Management

Setting Up a Build Environment

Your First Extension

Returning Values

Accepting Parameters

Working with Arrays and HashTables

The Resource Data Type

PHP4 Objects

PHP5 Objects

Startup, Shutdown, and a Few Points in Between

INI Settings

Accessing Streams

Implementing Streams

Diverting the Stream

Configuration and Linking

Extension Generators

Setting Up a Host Environment

Advanced Embedding

Appendix A. A Zend API Reference

Appendix B. PHPAPI

Appendix C. Extending and Embedding Cookbook

Appendix D. Additional Resources

Extending and Embedding PHP
Extending and Embedding PHP
ISBN: 067232704X
EAN: 2147483647
Year: 2007
Pages: 175
Authors: Sara Golemon © 2008-2020.
If you may any questions please contact us: