## The zend_module structure

The 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 and 5.2.

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):

Example#1 zend_module declaration in an example extension

    /* {{{ example_module_entry
     */
    zend_module_entry example_module_entry = {
    #if ZEND_MODULE_API_NO >= 20010901
        STANDARD_MODULE_HEADER,
    #endif
        "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),
    #if ZEND_MODULE_API_NO >= 20010901
        "0.1", /* Replace with version number for your extension */
    #endif
        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.2, along with a few relevant nearby constants:

Example#2 zend_module definition in PHP 5.2

    #define ZEND_MODULE_API_NO 20060613
    struct _zend_module_entry {
        unsigned short size;
        unsigned int zend_api;
        unsigned char zend_debug;
        unsigned char zts;
        struct _zend_ini_entry *ini_entry;
        struct _zend_module_dep *deps;
        char *name;
        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;
    };
    #define STANDARD_MODULE_HEADER_EX sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS
    #define STANDARD_MODULE_HEADER \
        STANDARD_MODULE_HEADER_EX, NULL, NULL
    #define ZE2_STANDARD_MODULE_HEADER \
        STANDARD_MODULE_HEADER_EX, ini_entries, NULL

    #define STANDARD_MODULE_PROPERTIES_EX 0, 0, NULL, 0