<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML ><HEAD ><TITLE >Source Discussion</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.79"><LINK REL="HOME" TITLE="Manual do PHP" HREF="index.html"><LINK REL="UP" TITLE="Zend API: Hackeando o Núcleo do PHP" HREF="zend.html"><LINK REL="PREVIOUS" TITLE="Resolução de Problemas" HREF="zend.troubleshooting.html"><LINK REL="NEXT" TITLE="Accepting Arguments" HREF="zend.arguments.html"><META HTTP-EQUIV="Content-type" CONTENT="text/html; charset=UTF-8"></HEAD ><BODY CLASS="sect1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" >Manual do PHP</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="zend.troubleshooting.html" ACCESSKEY="P" >Anterior</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" >Capítulo 46. Zend API: Hackeando o Núcleo do PHP</TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="zend.arguments.html" ACCESSKEY="N" >Próxima</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="zend.structure" >Source Discussion</A ></H1 ><P > Now 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. </P ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.module" >Module Structure</A ></H2 ><P > All PHP modules follow a common structure: <P ></P ><UL ><LI ><P > Header file inclusions (to include all required macros, API definitions, etc.) </P ></LI ><LI ><P > C declaration of exported functions (required to declare the Zend function block) </P ></LI ><LI ><P >Declaration of the Zend function block</P ></LI ><LI ><P >Declaration of the Zend module block</P ></LI ><LI ><P >Implementation of <B CLASS="function" >get_module()</B ></P ></LI ><LI ><P >Implementation of all exported functions</P ></LI ></UL ></P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.headers" >Header File Inclusions</A ></H2 ><P > The only header file you really have to include for your modules is <TT CLASS="filename" >php.h</TT >, located in the PHP directory. This file makes all macros and API definitions required to build new modules available to your code. </P ><P > <SPAN CLASS="emphasis" ><I CLASS="emphasis" >Tip:</I ></SPAN > 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 <TT CLASS="filename" >php.h</TT >. If you created your module using <TT CLASS="literal" >ext_skel</TT > you already have such a header file prepared. </P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.exporting-functions" >Declaring Exported Functions</A ></H2 ><P > To 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: <TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >ZEND_FUNCTION ( my_function );</PRE ></TD ></TR ></TABLE > </P ><P > <TT CLASS="literal" >ZEND_FUNCTION</TT > declares a new C function that complies with Zend's internal API. This means that the function is of type <TT CLASS="literal" >void</TT > and accepts <TT CLASS="literal" >INTERNAL_FUNCTION_PARAMETERS</TT > (another macro) as parameters. Additionally, it prefixes the function name with <TT CLASS="literal" >zif</TT >. The immediately expanded version of the above definitions would look like this: <TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >void zif_my_function ( INTERNAL_FUNCTION_PARAMETERS );</PRE ></TD ></TR ></TABLE > Expanding <TT CLASS="literal" >INTERNAL_FUNCTION_PARAMETERS</TT > results in the following: <TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >void zif_my_function( int ht , zval * return_value , zval * this_ptr , int return_value_used , zend_executor_globals * executor_globals );</PRE ></TD ></TR ></TABLE > </P ><P > 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 <CODE CLASS="envar" >zval</CODE > and <CODE CLASS="envar" >pval</CODE > are identical. <CODE CLASS="envar" >zval</CODE > is Zend's definition; <CODE CLASS="envar" >pval</CODE > is PHP's definition (actually, <CODE CLASS="envar" >pval</CODE > is an alias for <CODE CLASS="envar" >zval</CODE > now). As the macro <TT CLASS="literal" >INTERNAL_FUNCTION_PARAMETERS</TT > is a Zend macro, the above declaration contains <CODE CLASS="envar" >zval</CODE >. When writing code, you should always use <CODE CLASS="envar" >zval</CODE > to conform to the new Zend API. </P ><P > The parameter list of this declaration is very important; you should keep these parameters in mind (see <A HREF="zend.structure.html#tab.parameters" >Tabela 46-1</A > for descriptions). <DIV CLASS="table" ><A NAME="tab.parameters" ></A ><P ><B >Tabela 46-1. Zend's Parameters to Functions Called from PHP</B ></P ><TABLE BORDER="1" CLASS="CALSTABLE" ><COL WIDTH="1*" TITLE="col1"><COL WIDTH="1.79*" TITLE="col2"><TBODY ><TR ><TD >Parameter</TD ><TD >Description</TD ></TR ><TR ><TD ><CODE CLASS="envar" >ht</CODE ></TD ><TD > The number of arguments passed to the Zend function. You should not touch this directly, but instead use ZEND_NUM_ARGS() to obtain the value. </TD ></TR ><TR ><TD > <CODE CLASS="envar" >return_value</CODE ></TD ><TD > This variable is used to pass any return values of your function back to PHP. Access to this variable is best done using the predefined macros. For a description of these see below. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >this_ptr</CODE ></TD ><TD > Using this variable, you can gain access to the object in which your function is contained, if it's used within an object. Use the function <B CLASS="function" >getThis()</B > to obtain this pointer. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >return_value_used</CODE ></TD ><TD > This flag indicates whether an eventual return value from this function will actually be used by the calling script. <TT CLASS="literal" >0</TT > indicates that the return value is not used; <TT CLASS="literal" >1</TT > indicates that the caller expects a return value. Evaluation of this flag can be done to verify correct usage of the function as well as speed optimizations in case returning a value requires expensive operations (for an example, see how <TT CLASS="filename" >array.c</TT > makes use of this). </TD ></TR ><TR ><TD ><CODE CLASS="envar" >executor_globals</CODE ></TD ><TD > This variable points to global settings of the Zend engine. You'll find this useful when creating new variables, for example (more about this later). The executor globals can also be introduced to your function by using the macro <TT CLASS="literal" >TSRMLS_FETCH()</TT >. </TD ></TR ></TBODY ></TABLE ></DIV > </P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.function-block" >Declaration of the Zend Function Block</A ></H2 ><P > Now 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 <CODE CLASS="envar" >zend_function_entry</CODE >. 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, <CODE CLASS="envar" >zend_function_entry</CODE > is defined as shown in <A HREF="zend.structure.html#example.zend-function-entry" >Exemplo 46-4</A >. </P ><P > <TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="example.zend-function-entry" ></A ><P ><B >Exemplo 46-4. Internal declaration of <CODE CLASS="envar" >zend_function_entry</CODE >.</B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >typedef struct _zend_function_entry { char *fname; void (*handler)(INTERNAL_FUNCTION_PARAMETERS); unsigned char *func_arg_types; } zend_function_entry;</PRE ></TD ></TR ></TABLE ><DIV CLASS="informaltable" ><P ></P ><A NAME="AEN247266" ></A ><TABLE BORDER="1" CLASS="CALSTABLE" ><COL WIDTH="1*" TITLE="col1"><COL WIDTH="1.82*" TITLE="col2"><TBODY ><TR ><TD >Entry</TD ><TD >Description</TD ></TR ><TR ><TD ><CODE CLASS="envar" >fname</CODE ></TD ><TD > Denotes the function name as seen in PHP (for example, <TT CLASS="literal" >fopen</TT >, <TT CLASS="literal" >mysql_connect</TT >, or, in our example, <TT CLASS="literal" >first_module</TT >). </TD ></TR ><TR ><TD ><CODE CLASS="envar" >handler</CODE ></TD ><TD > Pointer to the C function responsible for handling calls to this function. For example, see the standard macro <TT CLASS="literal" >INTERNAL_FUNCTION_PARAMETERS</TT > discussed earlier. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >func_arg_types</CODE ></TD ><TD > Allows you to mark certain parameters so that they're forced to be passed by reference. You usually should set this to NULL. </TD ></TR ></TBODY ></TABLE ><P ></P ></DIV ></DIV ></TD ></TR ></TABLE > In the example above, the declaration looks like this: <TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >zend_function_entry firstmod_functions[] = { ZEND_FE(first_module, NULL) {NULL, NULL, NULL} };</PRE ></TD ></TR ></TABLE > You can see that the last entry in the list always has to be <TT CLASS="literal" >{NULL, NULL, NULL}</TT >. This marker has to be set for Zend to know when the end of the list of exported functions is reached. </P ><DIV CLASS="note" ><BLOCKQUOTE CLASS="note" ><P ><B >Nota: </B > You <SPAN CLASS="emphasis" ><I CLASS="emphasis" >cannot</I ></SPAN > use the predefined macros for the end marker, as these would try to refer to a function named "NULL"! </P ></BLOCKQUOTE ></DIV ><P > The macro <TT CLASS="literal" >ZEND_FE</TT > (short for 'Zend Function Entry') simply expands to a structure entry in <CODE CLASS="envar" >zend_function_entry</CODE >. Note that these macros introduce a special naming scheme to your functions - your C functions will be prefixed with <TT CLASS="literal" >zif_</TT >, meaning that <TT CLASS="literal" >ZEND_FE(first_module)</TT > will refer to a C function <B CLASS="function" >zif_first_module()</B >. If you want to mix macro usage with hand-coded entries (not a good practice), keep this in mind. </P ><P > Tip: Compilation errors that refer to functions named <B CLASS="function" >zif_*()</B > relate to functions defined with <TT CLASS="literal" >ZEND_FE</TT >. </P ><P > <A HREF="zend.structure.html#tab.funcdef-macros" >Tabela 46-2</A > shows a list of all the macros that you can use to define functions. </P ><DIV CLASS="table" ><A NAME="tab.funcdef-macros" ></A ><P ><B >Tabela 46-2. Macros for Defining Functions</B ></P ><TABLE BORDER="1" CLASS="CALSTABLE" ><COL WIDTH="1*" TITLE="col1"><COL WIDTH="1.08*" TITLE="col2"><TBODY ><TR ><TD >Macro Name</TD ><TD >Description</TD ></TR ><TR ><TD ><TT CLASS="literal" >ZEND_FE(name, arg_types)</TT ></TD ><TD > Defines a function entry of the name <CODE CLASS="envar" >name</CODE > in <CODE CLASS="envar" >zend_function_entry</CODE >. Requires a corresponding C function. <CODE CLASS="envar" >arg_types</CODE > needs to be set to <TT CLASS="literal" >NULL</TT >. This function uses automatic C function name generation by prefixing the PHP function name with <TT CLASS="literal" >zif_</TT >. For example, <TT CLASS="literal" >ZEND_FE("first_module", NULL)</TT > introduces a function <B CLASS="function" >first_module()</B > to PHP and links it to the C function <B CLASS="function" >zif_first_module()</B >. Use in conjunction with <TT CLASS="literal" >ZEND_FUNCTION</TT >. </TD ></TR ><TR ><TD > <TT CLASS="literal" >ZEND_NAMED_FE(php_name, name, arg_types)</TT > </TD ><TD > Defines a function that will be available to PHP by the name <CODE CLASS="envar" >php_name</CODE > and links it to the corresponding C function <CODE CLASS="envar" >name</CODE >. <CODE CLASS="envar" >arg_types</CODE > needs to be set to <TT CLASS="literal" >NULL</TT >. Use this function if you don't want the automatic name prefixing introduced by <TT CLASS="literal" >ZEND_FE</TT >. Use in conjunction with <TT CLASS="literal" >ZEND_NAMED_FUNCTION</TT >. </TD ></TR ><TR ><TD > <TT CLASS="literal" >ZEND_FALIAS(name, alias, arg_types)</TT > </TD ><TD > Defines an alias named <CODE CLASS="envar" >alias</CODE > for <CODE CLASS="envar" >name</CODE >. <CODE CLASS="envar" >arg_types</CODE > needs to be set to <TT CLASS="literal" >NULL</TT >. Doesn't require a corresponding C function; refers to the alias target instead. </TD ></TR ><TR ><TD ><TT CLASS="literal" >PHP_FE(name, arg_types)</TT ></TD ><TD > Old PHP API equivalent of <TT CLASS="literal" >ZEND_FE</TT >. </TD ></TR ><TR ><TD > <TT CLASS="literal" >PHP_NAMED_FE(runtime_name, name, arg_types)</TT > </TD ><TD > Old PHP API equivalent of <TT CLASS="literal" >ZEND_NAMED_FE</TT >. </TD ></TR ></TBODY ></TABLE ></DIV ><P > <SPAN CLASS="emphasis" ><I CLASS="emphasis" >Note:</I ></SPAN > You can't use <TT CLASS="literal" >ZEND_FE</TT > in conjunction with <TT CLASS="literal" >PHP_FUNCTION</TT >, or <TT CLASS="literal" >PHP_FE</TT > in conjunction with <TT CLASS="literal" >ZEND_FUNCTION</TT >. However, it's perfectly legal to mix <TT CLASS="literal" >ZEND_FE</TT > and <TT CLASS="literal" >ZEND_FUNCTION</TT > with <TT CLASS="literal" >PHP_FE</TT > and <TT CLASS="literal" >PHP_FUNCTION</TT > when staying with the same macro set for each function to be declared. But mixing is <SPAN CLASS="emphasis" ><I CLASS="emphasis" >not</I ></SPAN > recommended; instead, you're advised to use the <TT CLASS="literal" >ZEND_*</TT > macros only. </P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.module-block" >Declaration of the Zend Module Block</A ></H2 ><P > This block is stored in the structure <CODE CLASS="envar" >zend_module_entry</CODE > and contains all necessary information to describe the contents of this module to Zend. You can see the internal definition of this module in <A HREF="zend.structure.html#example.zend-module-entry" >Exemplo 46-5</A >. </P ><TABLE WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" CLASS="EXAMPLE" ><TR ><TD ><DIV CLASS="example" ><A NAME="example.zend-module-entry" ></A ><P ><B >Exemplo 46-5. Internal declaration of <CODE CLASS="envar" >zend_module_entry</CODE >.</B ></P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >typedef struct _zend_module_entry zend_module_entry; struct _zend_module_entry { unsigned short size; unsigned int zend_api; unsigned char zend_debug; unsigned char zts; char *name; 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; [ Rest of the structure is not interesting here ] };</PRE ></TD ></TR ></TABLE ><DIV CLASS="informaltable" ><P ></P ><A NAME="AEN247377" ></A ><TABLE BORDER="1" CLASS="CALSTABLE" ><COL WIDTH="1*" TITLE="col1"><COL WIDTH="1.69*" TITLE="col2"><THEAD ><TR ><TH >Entry</TH ><TH >Description</TH ></TR ></THEAD ><TBODY ><TR ><TD > <CODE CLASS="envar" >size</CODE >, <CODE CLASS="envar" >zend_api</CODE >, <CODE CLASS="envar" >zend_debug</CODE > and <CODE CLASS="envar" >zts</CODE > </TD ><TD > Usually filled with the <TT CLASS="literal" >"STANDARD_MODULE_HEADER"</TT >, which fills these four members with the size of the whole zend_module_entry, the <TT CLASS="literal" >ZEND_MODULE_API_NO</TT >, whether it is a debug build or normal build (<TT CLASS="literal" >ZEND_DEBUG</TT >) and if ZTS is enabled (<TT CLASS="literal" >USING_ZTS</TT >). </TD ></TR ><TR ><TD ><CODE CLASS="envar" >name</CODE ></TD ><TD > Contains the module name (for example, <TT CLASS="literal" >"File functions"</TT >, <TT CLASS="literal" >"Socket functions"</TT >, <TT CLASS="literal" >"Crypt"</TT >, etc.). This name will show up in <B CLASS="function" >phpinfo()</B >, in the section "Additional Modules." </TD ></TR ><TR ><TD ><CODE CLASS="envar" >functions</CODE ></TD ><TD > Points to the Zend function block, discussed in the preceding section. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >module_startup_func</CODE ></TD ><TD > This function is called once upon module initialization and can be used to do one-time initialization steps (such as initial memory allocation, etc.). To indicate a failure during initialization, return <TT CLASS="literal" >FAILURE</TT >; otherwise, <TT CLASS="literal" >SUCCESS</TT >. To mark this field as unused, use <TT CLASS="literal" >NULL</TT >. To declare a function, use the macro <TT CLASS="literal" >ZEND_MINIT</TT >. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >module_shutdown_func</CODE ></TD ><TD > This function is called once upon module shutdown and can be used to do one-time deinitialization steps (such as memory deallocation). This is the counterpart to <B CLASS="function" >module_startup_func()</B >. To indicate a failure during deinitialization, return <TT CLASS="literal" >FAILURE</TT >; otherwise, <TT CLASS="literal" >SUCCESS</TT >. To mark this field as unused, use <TT CLASS="literal" >NULL</TT >. To declare a function, use the macro <TT CLASS="literal" >ZEND_MSHUTDOWN</TT >. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >request_startup_func</CODE ></TD ><TD > This function is called once upon every page request and can be used to do one-time initialization steps that are required to process a request. To indicate a failure here, return <TT CLASS="literal" >FAILURE</TT >; otherwise, <TT CLASS="literal" >SUCCESS</TT >. <SPAN CLASS="emphasis" ><I CLASS="emphasis" >Note:</I ></SPAN > As dynamic loadable modules are loaded only on page requests, the request startup function is called right after the module startup function (both initialization events happen at the same time). To mark this field as unused, use <TT CLASS="literal" >NULL</TT >. To declare a function, use the macro <TT CLASS="literal" >ZEND_RINIT</TT >. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >request_shutdown_func</CODE ></TD ><TD > This function is called once after every page request and works as counterpart to <B CLASS="function" >request_startup_func()</B >. To indicate a failure here, return <TT CLASS="literal" >FAILURE</TT >; otherwise, <TT CLASS="literal" >SUCCESS</TT >. <SPAN CLASS="emphasis" ><I CLASS="emphasis" >Note:</I ></SPAN > As dynamic loadable modules are loaded only on page requests, the request shutdown function is immediately followed by a call to the module shutdown handler (both deinitialization events happen at the same time). To mark this field as unused, use <TT CLASS="literal" >NULL</TT >. To declare a function, use the macro <TT CLASS="literal" >ZEND_RSHUTDOWN</TT >. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >info_func</CODE ></TD ><TD > When <B CLASS="function" >phpinfo()</B > is called in a script, Zend cycles through all loaded modules and calls this function. Every module then has the chance to print its own "footprint" into the output page. Generally this is used to dump environmental or statistical information. To mark this field as unused, use <TT CLASS="literal" >NULL</TT >. To declare a function, use the macro <TT CLASS="literal" >ZEND_MINFO</TT >. </TD ></TR ><TR ><TD ><CODE CLASS="envar" >version</CODE ></TD ><TD > The version of the module. You can use <TT CLASS="literal" >NO_VERSION_YET</TT > if you don't want to give the module a version number yet, but we really recommend that you add a version string here. Such a version string can look like this (in chronological order): <TT CLASS="literal" >"2.5-dev"</TT >, <TT CLASS="literal" >"2.5RC1"</TT >, <TT CLASS="literal" >"2.5"</TT > or <TT CLASS="literal" >"2.5pl3"</TT >. </TD ></TR ><TR ><TD >Remaining structure elements</TD ><TD > These are used internally and can be prefilled by using the macro <TT CLASS="literal" >STANDARD_MODULE_PROPERTIES_EX</TT >. You should not assign any values to them. Use <TT CLASS="literal" >STANDARD_MODULE_PROPERTIES_EX</TT > only if you use global startup and shutdown functions; otherwise, use <TT CLASS="literal" >STANDARD_MODULE_PROPERTIES</TT > directly. </TD ></TR ></TBODY ></TABLE ><P ></P ></DIV ></DIV ></TD ></TR ></TABLE ><P > In our example, this structure is implemented as follows: <TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >zend_module_entry firstmod_module_entry = { STANDARD_MODULE_HEADER, "First Module", firstmod_functions, NULL, NULL, NULL, NULL, NULL, NO_VERSION_YET, STANDARD_MODULE_PROPERTIES, };</PRE ></TD ></TR ></TABLE > This is basically the easiest and most minimal set of values you could ever use. The module name is set to <TT CLASS="literal" >First Module</TT >, then the function list is referenced, after which all startup and shutdown functions are marked as being unused. </P ><P > For reference purposes, you can find a list of the macros involved in declared startup and shutdown functions in <A HREF="zend.structure.html#tab.init-shutdown" >Tabela 46-3</A >. 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 (<TT CLASS="literal" >INIT_FUNC_ARGS</TT > and <TT CLASS="literal" >SHUTDOWN_FUNC_ARGS</TT >), 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. </P ><DIV CLASS="table" ><A NAME="tab.init-shutdown" ></A ><P ><B >Tabela 46-3. Macros to Declare Startup and Shutdown Functions</B ></P ><TABLE BORDER="1" CLASS="CALSTABLE" ><COL WIDTH="1*" TITLE="col1"><COL WIDTH="1.41*" TITLE="col2"><TBODY ><TR ><TD >Macro</TD ><TD >Description</TD ></TR ><TR ><TD ><TT CLASS="literal" >ZEND_MINIT(module)</TT ></TD ><TD > Declares a function for module startup. The generated name will be <TT CLASS="literal" >zend_minit_<module></TT > (for example, <TT CLASS="literal" >zend_minit_first_module</TT >). Use in conjunction with <TT CLASS="literal" >ZEND_MINIT_FUNCTION</TT >. </TD ></TR ><TR ><TD ><TT CLASS="literal" >ZEND_MSHUTDOWN(module)</TT ></TD ><TD > Declares a function for module shutdown. The generated name will be <TT CLASS="literal" >zend_mshutdown_<module></TT > (for example, <TT CLASS="literal" >zend_mshutdown_first_module</TT >). Use in conjunction with <TT CLASS="literal" >ZEND_MSHUTDOWN_FUNCTION</TT >. </TD ></TR ><TR ><TD ><TT CLASS="literal" >ZEND_RINIT(module)</TT ></TD ><TD > Declares a function for request startup. The generated name will be <TT CLASS="literal" >zend_rinit_<module></TT > (for example, <TT CLASS="literal" >zend_rinit_first_module</TT >). Use in conjunction with <TT CLASS="literal" >ZEND_RINIT_FUNCTION</TT >. </TD ></TR ><TR ><TD ><TT CLASS="literal" >ZEND_RSHUTDOWN(module)</TT ></TD ><TD > Declares a function for request shutdown. The generated name will be <TT CLASS="literal" >zend_rshutdown_<module></TT > (for example, <TT CLASS="literal" >zend_rshutdown_first_module</TT >). Use in conjunction with <TT CLASS="literal" >ZEND_RSHUTDOWN_FUNCTION</TT >. </TD ></TR ><TR ><TD ><TT CLASS="literal" >ZEND_MINFO(module)</TT ></TD ><TD > Declares a function for printing module information, used when <B CLASS="function" >phpinfo()</B > is called. The generated name will be <TT CLASS="literal" >zend_info_<module></TT > (for example, <TT CLASS="literal" >zend_info_first_module</TT >). Use in conjunction with <TT CLASS="literal" >ZEND_MINFO_FUNCTION</TT >. </TD ></TR ></TBODY ></TABLE ></DIV ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.get-module" >Creation of <B CLASS="function" >get_module()</B ></A ></H2 ><P > This function is special to all dynamic loadable modules. Take a look at the creation via the <TT CLASS="literal" >ZEND_GET_MODULE</TT > macro first: </P ><TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >#if COMPILE_DL_FIRSTMOD ZEND_GET_MODULE(firstmod) #endif</PRE ></TD ></TR ></TABLE ><P > The function implementation is surrounded by a conditional compilation statement. This is needed since the function <B CLASS="function" >get_module()</B > is only required if your module is built as a dynamic extension. By specifying a definition of <TT CLASS="literal" >COMPILE_DL_FIRSTMOD</TT > 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 <B CLASS="function" >get_module()</B > is simply left out. </P ><P > <B CLASS="function" >get_module()</B > is called by Zend at load time of the module. You can think of it as being invoked by the <B CLASS="function" >dl()</B > 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. </P ><P > If you don't implement a <B CLASS="function" >get_module()</B > function in your dynamic loadable module, Zend will compliment you with an error message when trying to access it. </P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.implementation" >Implementation of All Exported Functions</A ></H2 ><P >Implementing the exported functions is the final step. The example function in <TT CLASS="literal" >first_module</TT > looks like this: <TABLE BORDER="0" BGCOLOR="#E0E0E0" CELLPADDING="5" ><TR ><TD ><PRE CLASS="programlisting" >ZEND_FUNCTION(first_module) { long parameter; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &parameter) == FAILURE) { return; } RETURN_LONG(parameter); }</PRE ></TD ></TR ></TABLE > The function declaration is done using <TT CLASS="literal" >ZEND_FUNCTION</TT >, which corresponds to <TT CLASS="literal" >ZEND_FE</TT > in the function entry table (discussed earlier). </P ><P > After the declaration, code for checking and retrieving the function's arguments, argument conversion, and return value generation follows (more on this later). </P ></DIV ><DIV CLASS="sect2" ><H2 CLASS="sect2" ><A NAME="zend.structure.summary" >Summary</A ></H2 ><P > That'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. </P ><P > Now, in the following sections, read on about how to make use of PHP's internals to build powerful extensions. </P ></DIV ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="zend.troubleshooting.html" ACCESSKEY="P" >Anterior</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Principal</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="zend.arguments.html" ACCESSKEY="N" >Próxima</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >Resolução de Problemas</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="zend.html" ACCESSKEY="U" >Acima</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Accepting Arguments</TD ></TR ></TABLE ></DIV ></BODY ></HTML >