Sophie

Sophie

distrib > Mandriva > 2008.1 > x86_64 > by-pkgid > 05cd670d8a02b2b4a0ffb1756f2e8308 > files > 11871

php-manual-zh-5.2.4-1mdv2008.1.noarch.rpm

<!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="PHP 手册"
HREF="index.html"><LINK
REL="UP"
TITLE="Zend API:深入 PHP 内核"
HREF="zend.html"><LINK
REL="PREVIOUS"
TITLE="Troubleshooting"
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"
>PHP 手册</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="zend.troubleshooting.html"
ACCESSKEY="P"
>上一页</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
>章 46. Zend API:深入 PHP 内核</TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="zend.arguments.html"
ACCESSKEY="N"
>下一页</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
>&#13;   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
>&#13;    All PHP modules follow a common structure: 
    <P
></P
><UL
><LI
><P
>&#13;       Header file inclusions (to include all required macros, API
       definitions, etc.)
      </P
></LI
><LI
><P
>&#13;       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
>&#13;    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
>&#13;    <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
>&#13;    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
>&#13;    <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
>&#13;    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
>&#13;    The parameter list of this declaration is very important; you should keep these parameters in mind (see <A
HREF="zend.structure.html#tab.parameters"
>表 46-1</A
> for descriptions). 
    <DIV
CLASS="table"
><A
NAME="tab.parameters"
></A
><P
><B
>表 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
>&#13;          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
>&#13;          <CODE
CLASS="envar"
>return_value</CODE
></TD
><TD
>&#13;          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
>&#13;          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
>&#13;          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
>&#13;          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
>&#13;    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"
>例 46-4</A
>. 
   </P
><P
>&#13;    <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
>例 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="AEN255061"
></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
>&#13;          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
>&#13;          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
>&#13;          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
>注意: </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
>&#13;    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
>&#13;    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
>&#13;    <A
HREF="zend.structure.html#tab.funcdef-macros"
>表 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
>表 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
>&#13;         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
>&#13;         <TT
CLASS="literal"
>ZEND_NAMED_FE(php_name, name, arg_types)</TT
>
        </TD
><TD
>&#13;         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
>&#13;         <TT
CLASS="literal"
>ZEND_FALIAS(name, alias, arg_types)</TT
>
        </TD
><TD
>&#13;         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
>&#13;         Old PHP API equivalent of <TT
CLASS="literal"
>ZEND_FE</TT
>.
        </TD
></TR
><TR
><TD
>&#13;         <TT
CLASS="literal"
>PHP_NAMED_FE(runtime_name, name, arg_types)</TT
>
        </TD
><TD
>&#13;         Old PHP API equivalent of <TT
CLASS="literal"
>ZEND_NAMED_FE</TT
>.
        </TD
></TR
></TBODY
></TABLE
></DIV
><P
>&#13;    <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
>&#13;    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"
>例 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
>例 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="AEN255172"
></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
>&#13;         <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
>&#13;         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
>&#13;         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
>&#13;         Points to the Zend function block, discussed in the preceding
         section.
        </TD
></TR
><TR
><TD
><CODE
CLASS="envar"
>module_startup_func</CODE
></TD
><TD
>&#13;         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
>&#13;         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
>&#13;         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
>&#13;         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
>&#13;         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
>&#13;         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
>&#13;         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
>&#13;    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
>&#13;    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"
>表 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
>表 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
>&#13;         Declares a function for module startup. The generated name will
         be <TT
CLASS="literal"
>zend_minit_&#60;module&#62;</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
>&#13;         Declares a function for module shutdown. The generated name
         will be <TT
CLASS="literal"
>zend_mshutdown_&#60;module&#62;</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
>&#13;         Declares a function for request startup. The generated name
         will be <TT
CLASS="literal"
>zend_rinit_&#60;module&#62;</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
>&#13;         Declares a function for request shutdown. The generated name
         will be <TT
CLASS="literal"
>zend_rshutdown_&#60;module&#62;</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
>&#13;         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_&#60;module&#62;</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
>&#13;    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
>&#13;    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
>&#13;    <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
>&#13;    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", &#38;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
>&#13;    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
>&#13;    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
>&#13;    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"
>上一页</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="index.html"
ACCESSKEY="H"
>起始页</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="zend.arguments.html"
ACCESSKEY="N"
>下一页</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>Troubleshooting</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="zend.html"
ACCESSKEY="U"
>上一级</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>Accepting Arguments</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>