home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Programming PHPProgramming PHPSearch this book

14.10. Global Variables

To 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.3. Internal Extension Globals

Sometimes 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);




Library Navigation Links

Copyright © 2003 O'Reilly & Associates. All rights reserved.