Source DiscussionNow that you've got a safe build environment and you're able to include the modules into PHP files, it's time to discuss how everything works. Module StructureAll PHP modules follow a common structure:
Header File InclusionsThe only header file you really have to include for your modules is php.h, located in the PHP directory. This file makes all macros and API definitions required to build new modules available to your code. Tip: It's good practice to create a separate header file for your module that contains module-specific definitions. This header file should contain all the forward definitions for exported functions and include php.h. If you created your module using ext_skel you already have such a header file prepared. Declaring Exported FunctionsTo declare functions that are to be exported (i.e., made available to PHP as new native functions), Zend provides a set of macros. A sample declaration looks like this:
ZEND_FUNCTION declares a new C function that complies with Zend's internal API. This means that the function is of type void and accepts INTERNAL_FUNCTION_PARAMETERS (another macro) as parameters. Additionally, it prefixes the function name with zif. The immediately expanded version of the above definitions would look like this:
Since the interpreter and executor core have been separated from the main PHP package, a second API defining macros and function sets has evolved: the Zend API. As the Zend API now handles quite a few of the responsibilities that previously belonged to PHP, a lot of PHP functions have been reduced to macros aliasing to calls into the Zend API. The recommended practice is to use the Zend API wherever possible, as the old API is only preserved for compatibility reasons. For example, the types zval and pval are identical. zval is Zend's definition; pval is PHP's definition (actually, pval is an alias for zval now). As the macro INTERNAL_FUNCTION_PARAMETERS is a Zend macro, the above declaration contains zval. When writing code, you should always use zval to conform to the new Zend API. The parameter list of this declaration is very important; you should keep these parameters in mind (see 表格 45-1 for descriptions). 表格 45-1. Zend's Parameters to Functions Called from PHP
Declaration of the Zend Function BlockNow that you have declared the functions to be exported, you also have to introduce them to Zend. Introducing the list of functions is done by using an array of zend_function_entry. This array consecutively contains all functions that are to be made available externally, with the function's name as it should appear in PHP and its name as defined in the C source. Internally, zend_function_entry is defined as shown in 例子 45-4.
The macro ZEND_FE (short for 'Zend Function Entry') simply expands to a structure entry in zend_function_entry. Note that these macros introduce a special naming scheme to your functions - your C functions will be prefixed with zif_, meaning that ZEND_FE(first_module) will refer to a C function zif_first_module(). If you want to mix macro usage with hand-coded entries (not a good practice), keep this in mind. Tip: Compilation errors that refer to functions named zif_*() relate to functions defined with ZEND_FE. 表格 45-2 shows a list of all the macros that you can use to define functions. 表格 45-2. Macros for Defining Functions
Note: You can't use ZEND_FE in conjunction with PHP_FUNCTION, or PHP_FE in conjunction with ZEND_FUNCTION. However, it's perfectly legal to mix ZEND_FE and ZEND_FUNCTION with PHP_FE and PHP_FUNCTION when staying with the same macro set for each function to be declared. But mixing is not recommended; instead, you're advised to use the ZEND_* macros only. Declaration of the Zend Module BlockThis block is stored in the structure zend_module_entry and contains all necessary information to describe the contents of this module to Zend. You can see the internal definition of this module in 例子 45-5.
In our example, this structure is implemented as follows:
For reference purposes, you can find a list of the macros involved in declared startup and shutdown functions in 表格 45-3. These are not used in our basic example yet, but will be demonstrated later on. You should make use of these macros to declare your startup and shutdown functions, as these require special arguments to be passed (INIT_FUNC_ARGS and SHUTDOWN_FUNC_ARGS), which are automatically included into the function declaration when using the predefined macros. If you declare your functions manually and the PHP developers decide that a change in the argument list is necessary, you'll have to change your module sources to remain compatible. 表格 45-3. Macros to Declare Startup and Shutdown Functions
Creation of get_module()This function is special to all dynamic loadable modules. Take a look at the creation via the ZEND_GET_MODULE macro first:
The function implementation is surrounded by a conditional compilation statement. This is needed since the function get_module() is only required if your module is built as a dynamic extension. By specifying a definition of COMPILE_DL_FIRSTMOD in the compiler command (see above for a discussion of the compilation instructions required to build a dynamic extension), you can instruct your module whether you intend to build it as a dynamic extension or as a built-in module. If you want a built-in module, the implementation of get_module() is simply left out. get_module() is called by Zend at load time of the module. You can think of it as being invoked by the dl() call in your script. Its purpose is to pass the module information block back to Zend in order to inform the engine about the module contents. If you don't implement a get_module() function in your dynamic loadable module, Zend will compliment you with an error message when trying to access it. Implementation of All Exported FunctionsImplementing the exported functions is the final step. The example function in first_module looks like this:
After the declaration, code for checking and retrieving the function's arguments, argument conversion, and return value generation follows (more on this later). SummaryThat's it, basically - there's nothing more to implementing PHP modules. Built-in modules are structured similarly to dynamic modules, so, equipped with the information presented in the previous sections, you'll be able to fight the odds when encountering PHP module source files. Now, in the following sections, read on about how to make use of PHP's internals to build powerful extensions. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||