14.10. Global VariablesTo access an internal PHP global variable from a function in your extension, you first have to determine what kind of global variable it is. There are three main types: SAPI globals, executor globals, and extension globals. 14.10.1. SAPI Globals (SG)SAPI is the Server Abstraction API. It contains any variables related to the web server under which PHP is running. Note that not all SAPI modules are related to web servers. The command-line version of PHP, for example, uses the CGI SAPI layer. There is also a Java SAPI module. You can check which SAPI module you are running under by including SAPI.h and then checking sapi_module.name: #include <SAPI.h> /* then in a function */ printf("the SAPI module is %s\n", sapi_module.name); See the sapi_globals_struct in the main/SAPI.h file for a list of available SAPI globals. For example, to access the default_mimetype SAPI global, you would use: SG(default_mimetype) Some elements of the SAPI globals structure are themselves structures with fields. For example, to access the request_uri, use: SG(request_info).request_uri 14.10.2. Executor Globals (EG)These are runtime globals defined internally by the Zend executor. The most common EG variables are symbol_table (which holds the main symbol table) and active_symbol_table (which holds the currently visible symbols). For example, to see if the user-space $foo variable has been set, you could do: zval **tmp; if(zend_hash_find(&EG(symbol_table), "foo", sizeof("foo"), (void **)&tmp) == SUCCESS) { RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); } else { RETURN_FALSE; } 14.10.3. Internal Extension GlobalsSometimes you need extensionwide global C variables. Since an extension has to be thread-safe, global variables are a problem. You can solve this problem by creating a struct—each would-be global variable becomes a field in the struct. When compiled as a thread-safe extension, macros take care of passing this struct around. When compiled as a non-thread-safe extension, the struct is a true global struct that is accessed directly. This way, the non-thread-safe builds do not suffer the slight performance penalty of passing around this global struct. These macros look something like this for a thread-safe build: #define TSRMLS_FETCH( ) void ***tsrm_ls = (void ***) ts_resource_ex(0, NULL) #define TSRMG(id,type,el) (((type) (*((void ***) \ tsrm_ls))[TSRM_UNSHUFFLE_RSRC_ID(id)])->el) #define TSRMLS_D void ***tsrm_ls #define TSRMLS_DC , TSRMLS_D #define TSRMLS_C tsrm_ls #define TSRMLS_CC , TSRMLS_C For the non-thread-safe build, they don't do anything and are simply defined as: #define TSRMLS_FETCH( ) #define TSRMLS_D void #define TSRMLS_DC #define TSRMLS_C #define TSRMLS_CC #endif /* ZTS */ So, to create extensionwide global variables, you first need to create a struct in which to store them, along with the thread-safe and non-thread-safe access macros. The struct looks like this in the php_ foo.h header file: ZEND_BEGIN_MODULE_GLOBALS(foo) int some_integer; char *some_string; ZEND_END_MODULE_GLOBALS(foo) #ifdef ZTS # define FOO_G(v) TSRMG(foo_globals_id, zend_foo_globals *, v) #else # define FOO_G(v) (foo_globals.v) #endif The ext_skel tool creates most of this for you. You simply have to uncomment the right sections. In the main extension file, foo.c, you need to declare that your extension has globals and define a function to initialize each member of your global struct: ZEND_DECLARE_MODULE_GLOBALS(foo) static void php_foo_init_globals(zend_foo_globals *foo_globals) { foo_globals->some_integer = 0; foo_globals->some_string = NULL; } To have your initialization function called on module initialization, add this inside the PHP_MINIT_FUNCTION( ): ZEND_INIT_MODULE_GLOBALS(foo, php_foo_init_globals, NULL); To access one of these globals, some_integer or some_string, use FOO_G(some_integer) or FOO_G(some_string). Note that the struct must be available in the function in order to use the FOO_G( ) macro. For all standard PHP functions, the global struct is automatically and invisibly passed in. However, if you write your own utility functions that need to access the global values, you'll have to pass in the struct yourself. The TSRMLS_CC macro does this for you, so calls to your utility functions look like: foo_utility_function(my_arg TSRMLS_CC); When you declare foo_utility_function( ), use the TSRMLS_DC macro to receive the global struct: static void foo_utility_function(int my_arg TSRMLS_DC); Copyright © 2003 O'Reilly & Associates. All rights reserved. |
|