|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The zend_module structureThe main source file of a PHP extension contains several new constructs for a C programmer. The most important of these, the one touched first when starting a new extension, is the zend_module structure. This structure contains a wealth of information that tells the Zend Engine about the extension's dependencies, version, callbacks, and other critical data. The structure has mutated considerably over time; this section will focus on the structure as it has appeared since PHP 5.0, and will identify the very few parts which have changed in PHP 5.1, 5.2, and 5.3. The zend_module declaration from example.c looks like this before any code has been written. The example file was generated by ext_skel --extname=example, with some obsolete constructs removed: Пример #1 zend_module declaration in an example extension
/* {{{ example_module_entry
*/
zend_module_entry example_module_entry = {
STANDARD_MODULE_HEADER,
"example",
example_functions,
PHP_MINIT(example),
PHP_MSHUTDOWN(example),
PHP_RINIT(example), /* Replace with NULL if there's nothing to do at request start */
PHP_RSHUTDOWN(example), /* Replace with NULL if there's nothing to do at request end */
PHP_MINFO(example),
"0.1", /* Replace with version number for your extension */
STANDARD_MODULE_PROPERTIES
};
/* }}} */
This may look a bit daunting at first glance, but most of it is very simple to understand. Here's the declaration of zend_module from zend_modules.h in PHP 5.3: Пример #2 zend_module definition in PHP 5.3
struct _zend_module_entry {
unsigned short size;
unsigned int zend_api;
unsigned char zend_debug;
unsigned char zts;
const struct _zend_ini_entry *ini_entry;
const struct _zend_module_dep *deps;
const char *name;
const struct _zend_function_entry *functions;
int (*module_startup_func)(INIT_FUNC_ARGS);
int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS);
int (*request_startup_func)(INIT_FUNC_ARGS);
int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS);
void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS);
char *version;
size_t globals_size;
#ifdef ZTS
ts_rsrc_id* globals_id_ptr;
#else
void* globals_ptr;
#endif
void (*globals_ctor)(void *global TSRMLS_DC);
void (*globals_dtor)(void *global TSRMLS_DC);
int (*post_deactivate_func)(void);
int module_started;
unsigned char type;
void *handle;
int module_number;
};
Many of these fields will never be touched by an extension writer. There are a number of standard macros that set them to their proper values automatically. The macro STANDARD_MODULE_HEADER fills in everything up to the deps field. Alternatively, the STANDARD_MODULE_HEADER_EX will leave the deps field empty for the developer's use. The developer is always responsible for everything from name to version. After that, the STANDARD_MODULE_PROPERTIES macro will fill in the rest of the structure, or the STANDARD_MODULE_PROPERTIES_EX macro can be used to leave the extension globals and post-deactivation function fields unfilled. Most modern extensions will make use of module globals.
Filling in the structure in a practical situationWith all these fields to play with, it can be confusing to know which to use for what purpose. Here is the zend_module definition from the "counter" example extension. Пример #3 Counter extension module definition
/* {{{ counter_module_entry
*/
zend_module_entry counter_module_entry = {
STANDARD_MODULE_HEADER,
"counter",
counter_functions,
PHP_MINIT(counter),
PHP_MSHUTDOWN(counter),
PHP_RINIT(counter),
PHP_RSHUTDOWN(counter),
PHP_MINFO(counter),
NO_VERSION_YET,
PHP_MODULE_GLOBALS(counter),
PHP_GINIT(counter),
PHP_GSHUTDOWN(counter),
NULL,
STANDARD_MODULE_PROPERTIES_EX
};
/* }}} */
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||