File: structure.xml

package info (click to toggle)
php-doc 20100521-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze, wheezy
  • size: 59,992 kB
  • ctags: 4,085
  • sloc: xml: 796,833; php: 21,338; cpp: 500; sh: 117; makefile: 58; awk: 28
file content (730 lines) | stat: -rw-r--r-- 30,308 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
<?xml version="1.0" encoding="utf-8"?>
 <!-- $Revision: 297078 $ -->
 <sect2 xml:id="internals2.ze1.zendapi.structure" xmlns="http://docbook.org/ns/docbook"> 
  <title>Source Discussion</title> 
  <para>
   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.
  </para> 
  <sect3 xml:id="internals2.ze1.zendapi.structure.module"> 
   <title>Module Structure</title> 
   <para>
    All PHP modules follow a common structure: 
    <itemizedlist> 
     <listitem> 
      <para>
       Header file inclusions (to include all required macros, API
       definitions, etc.)
      </para> 
     </listitem> 
     <listitem> 
      <para>
       C declaration of exported functions (required to declare the Zend
  function block)
      </para> 
     </listitem> 
     <listitem> 
      <para>Declaration of the Zend function block</para> 
     </listitem> 
     <listitem> 
      <para>Declaration of the Zend module block</para> 
     </listitem> 
     <listitem> 
      <para>Implementation of <function>get_module</function></para> 
     </listitem> 
     <listitem> 
      <para>Implementation of all exported functions</para> 
     </listitem> 
    </itemizedlist></para> 
  </sect3>

  <sect3 xml:id="internals2.ze1.zendapi.structure.headers">
   <title>Header File Inclusions</title>
   <para>
    The only header file you really have to include for your modules is
    <filename>php.h</filename>, located in the PHP directory. This file makes all
    macros and API definitions required to build new modules available to your
    code. 
   </para>
   <para>
    <emphasis>Tip:</emphasis> 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
    <filename>php.h</filename>. If you created your module using
    <literal>ext_skel</literal> you already have such a header file
    prepared.
   </para>
  </sect3>

  <sect3 xml:id="internals2.ze1.zendapi.structure.exporting-functions"> 
   <title>Declaring Exported Functions</title> 
   <para>
    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: 
    <programlisting role="c">
<![CDATA[
ZEND_FUNCTION ( my_function );
]]>
    </programlisting>
   </para> 
   <para>
    <literal>ZEND_FUNCTION</literal> declares a new C function that complies
    with Zend's internal API. This means that the function is of
    type <literal>void</literal> and
    accepts <literal>INTERNAL_FUNCTION_PARAMETERS</literal> (another macro) as
    parameters. Additionally, it prefixes the function name with
    <literal>zif</literal>. The immediately expanded version of the above
    definitions would look like this: 
    <programlisting role="c">
<![CDATA[
void zif_my_function ( INTERNAL_FUNCTION_PARAMETERS );
]]>
    </programlisting>
    Expanding <literal>INTERNAL_FUNCTION_PARAMETERS</literal> 
    results in the following:
    <programlisting role="c">
<![CDATA[
void zif_my_function( int ht
                    , zval * return_value
                    , zval * this_ptr
                    , int return_value_used
                    , zend_executor_globals * executor_globals
                    );
]]>
    </programlisting> 
   </para>
   <para>
    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 <envar>zval</envar>
    and <envar>pval</envar> are identical. <envar>zval</envar> is
    Zend's definition; <envar>pval</envar> is PHP's definition
    (actually, <envar>pval</envar> is an alias for <envar>zval</envar>
    now). As the macro <literal>INTERNAL_FUNCTION_PARAMETERS</literal>
    is a Zend macro, the above declaration contains
    <envar>zval</envar>. When writing code, you should always use
    <envar>zval</envar> to conform to the new Zend API.
   </para>
   <para>
    The parameter list of this declaration is very important; you should keep these parameters in mind (see <xref linkend="internals2.ze1.zendapi.tab.parameters"/> for descriptions).
    <table xml:id="internals2.ze1.zendapi.tab.parameters">
     <title>Zend's Parameters to Functions Called from PHP</title> 
      <tgroup cols="2">
       <colspec colnum="1" colname="col1" colwidth="1.00*"/>
       <colspec colnum="2" colname="col2" colwidth="1.79*"/> 
       <tbody> 
        <row> 
         <entry colname="col1">Parameter</entry> 
         <entry colname="col2">Description</entry> 
        </row> 
        <row> 
         <entry colname="col1"><envar>ht</envar></entry> 
         <entry colname="col2">
          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.
         </entry> 
        </row> 
        <row> 
         <entry colname="col1">
          <envar>return_value</envar></entry> 
         <entry colname="col2">
          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.
         </entry> 
        </row> 
        <row> 
         <entry colname="col1"><envar>this_ptr</envar></entry> 
         <entry colname="col2">
          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 <function>getThis</function> to obtain this pointer.
         </entry> 
        </row> 
        <row> 
         <entry colname="col1"><envar>return_value_used</envar></entry> 
         <entry colname="col2">
          This flag indicates whether an eventual return value
          from this function will actually be used by the calling script.
          <literal>0</literal> indicates that the return value is not used;
          <literal>1</literal> 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 <filename>array.c</filename> makes use of
          this).
         </entry> 
        </row> 
        <row> 
         <entry colname="col1"><envar>executor_globals</envar></entry> 
         <entry colname="col2">
          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 <literal>TSRMLS_FETCH()</literal>.
         </entry> 
        </row> 
       </tbody> 
      </tgroup> 
   </table>
  </para> 
  </sect3> 
  
  <sect3 xml:id="internals2.ze1.zendapi.structure.function-block"> 
   <title>Declaration of the Zend Function Block</title> 
   <para>
    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 <envar>zend_function_entry</envar>. 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, <envar>zend_function_entry</envar> is defined as shown in
    <xref linkend="internals2.ze1.zendapi.example.zend-function-entry"/>.
   </para>
   <para>
    <example xml:id="internals2.ze1.zendapi.example.zend-function-entry">
     <title>Internal declaration of <envar>zend_function_entry</envar>.</title> 
     <programlisting role="c">
<![CDATA[
typedef struct _zend_function_entry {
    char *fname;
    void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
    unsigned char *func_arg_types;
} zend_function_entry;
]]>
     </programlisting> 
     <informaltable> 
      <tgroup cols="2">
       <colspec colnum="1" colname="col1" colwidth="1.00*"/>
       <colspec colnum="2" colname="col2" colwidth="1.82*"/> 
       <tbody> 
        <row> 
         <entry colname="col1">Entry</entry> 
         <entry colname="col2">Description</entry> 
        </row> 
        <row> 
         <entry colname="col1"><envar>fname</envar></entry> 
         <entry colname="col2">
          Denotes the function name as seen in PHP (for
          example, <literal>fopen</literal>, <literal>mysql_connect</literal>, or, in our
          example, <literal>first_module</literal>).
         </entry> 
        </row> 
        <row> 
         <entry colname="col1"><envar>handler</envar></entry> 
         <entry colname="col2">
          Pointer to the C function responsible for handling calls
          to this function. For example, see the standard macro
          <literal>INTERNAL_FUNCTION_PARAMETERS</literal> discussed earlier.
         </entry> 
        </row> 
        <row> 
         <entry colname="col1"><envar>func_arg_types</envar></entry> 
         <entry colname="col2">
          Allows you to mark certain parameters so that they're forced
          to be passed by reference. You usually should set this to
          NULL.
         </entry> 
        </row> 
       </tbody> 
      </tgroup>
     </informaltable> 
    </example>
    In the example above, the declaration looks like this: 
    <programlisting role="c">
<![CDATA[
zend_function_entry firstmod_functions[] =
{
    ZEND_FE(first_module, NULL)
    {NULL, NULL, NULL}
};
]]>
    </programlisting>
    You can see that the last entry in the list always has to be 
    <literal>{NULL, NULL, NULL}</literal>. 
    This marker has to be set for Zend to know when the end of the 
    list of exported functions is reached. 
   </para>
   <note>
    <para>
     You <emphasis>cannot</emphasis> use the predefined macros for the
     end marker, as these would try to refer to a function named "NULL"!
    </para>
   </note>
   <para>
    The macro <literal>ZEND_FE</literal> (short for 'Zend Function
    Entry') simply expands to a structure entry in
    <envar>zend_function_entry</envar>. Note that these macros
    introduce a special naming scheme to your functions - your C
    functions will be prefixed with <literal>zif_</literal>, meaning
    that <literal>ZEND_FE(first_module)</literal> will refer to a C
    function <function>zif_first_module</function>. If you want to mix
    macro usage with hand-coded entries (not a good practice), keep
    this in mind. 
   </para>
   <para>
    Tip: Compilation errors that refer to functions
    named <function>zif_*</function> relate to functions defined
    with <literal>ZEND_FE</literal>.
   </para> 
   <para>
    <xref linkend="internals2.ze1.zendapi.tab.funcdef-macros"/> shows a list of all the macros 
    that you can use to define functions.
   </para> 
   <table xml:id="internals2.ze1.zendapi.tab.funcdef-macros">
    <title>Macros for Defining Functions</title> 
     <tgroup cols="2">
      <colspec colnum="1" colname="col1" colwidth="1.00*"/>
      <colspec colnum="2" colname="col2" colwidth="1.08*"/> 
      <tbody> 
       <row> 
        <entry colname="col1">Macro Name</entry> 
        <entry colname="col2">Description</entry> 
       </row> 
       <row> 
        <entry colname="col1"><literal>ZEND_FE(name, arg_types)</literal></entry> 
        <entry colname="col2">
         Defines a function entry of the name <envar>name</envar> in
         <envar>zend_function_entry</envar>. Requires a corresponding C
         function. <envar>arg_types</envar> needs to be set to <literal>NULL</literal>.
         This function uses automatic C function name generation by prefixing the PHP
         function name with <literal>zif_</literal>.
         For example, <literal>ZEND_FE("first_module", NULL)</literal> introduces a
         function <function>first_module</function> to PHP and links it to the C
         function <function>zif_first_module</function>. Use in conjunction
         with <literal>ZEND_FUNCTION</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1">
         <literal>ZEND_NAMED_FE(php_name, name, arg_types)</literal>
        </entry> 
        <entry colname="col2">
         Defines a function that will be available to PHP by the
         name <envar>php_name</envar> and links it to the corresponding C
         function <envar>name</envar>. <envar>arg_types</envar> needs to be set
         to <literal>NULL</literal>. Use this function if you don't want the automatic
         name prefixing introduced by <literal>ZEND_FE</literal>. Use in conjunction
         with <literal>ZEND_NAMED_FUNCTION</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1">
         <literal>ZEND_FALIAS(name, alias, arg_types)</literal>
        </entry> 
        <entry colname="col2">
         Defines an alias named <envar>alias</envar> for
         <envar>name</envar>. <envar>arg_types</envar> needs to be set
         to <literal>NULL</literal>. Doesn't require a corresponding C
         function; refers to the alias target instead.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><literal>PHP_FE(name, arg_types)</literal></entry> 
        <entry colname="col2">
         Old PHP API equivalent of <literal>ZEND_FE</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1">
         <literal>PHP_NAMED_FE(runtime_name, name, arg_types)</literal>
        </entry> 
        <entry colname="col2">
         Old PHP API equivalent of <literal>ZEND_NAMED_FE</literal>.
        </entry> 
       </row> 
      </tbody> 
     </tgroup> 
   </table> 
   <para>
    <emphasis>Note:</emphasis> You can't use
    <literal>ZEND_FE</literal> in conjunction with
    <literal>PHP_FUNCTION</literal>, or <literal>PHP_FE</literal> in
    conjunction with <literal>ZEND_FUNCTION</literal>. However, it's
    perfectly legal to mix <literal>ZEND_FE</literal> and
    <literal>ZEND_FUNCTION</literal> with <literal>PHP_FE</literal>
    and <literal>PHP_FUNCTION</literal> when staying with the same
    macro set for each function to be declared. But mixing is
    <emphasis>not</emphasis> recommended; instead, you're advised to
    use the <literal>ZEND_*</literal> macros only.
   </para> 
  </sect3> 

  <sect3 xml:id="internals2.ze1.zendapi.structure.module-block"> 
   <title>Declaration of the Zend Module Block</title> 
   <para>
    This block is stored in the structure
    <envar>zend_module_entry</envar> and contains all necessary
    information to describe the contents of this module to Zend. You can
    see the internal definition of this module in 
    <xref linkend="internals2.ze1.zendapi.example.zend-module-entry"/>.
   </para>
   <example xml:id="internals2.ze1.zendapi.example.zend-module-entry">
    <title>Internal declaration of <envar>zend_module_entry</envar>.</title> 
    <programlisting role="c">
<![CDATA[
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 ]

};
]]>
    </programlisting>
    <informaltable> 
     <tgroup cols="2">
      <colspec colnum="1" colname="col1" colwidth="1.00*"/>
      <colspec colnum="2" colname="col2" colwidth="1.69*"/> 
      <thead> 
       <row> 
        <entry colname="col1">Entry</entry> 
        <entry colname="col2">Description</entry> 
       </row> 
      </thead> 
    <tbody> 
       <row> 
        <entry colname="col1">
         <envar>size</envar>, <envar>zend_api</envar>,
         <envar>zend_debug</envar> and <envar>zts</envar>
        </entry> 
        <entry colname="col2">
         Usually filled with the
         <literal>"STANDARD_MODULE_HEADER"</literal>, which fills these
         four members with the size of the whole zend_module_entry, the
         <literal>ZEND_MODULE_API_NO</literal>, whether it is a debug
         build or normal build (<literal>ZEND_DEBUG</literal>) and if
         ZTS is enabled (<literal>USING_ZTS</literal>).
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><envar>name</envar></entry> 
        <entry colname="col2">
         Contains the module name (for example, <literal>"File
          functions"</literal>, <literal>"Socket functions"</literal>,
         <literal>"Crypt"</literal>, etc.). This name will show up in
         <function>phpinfo</function>, in the section "Additional
         Modules."
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><envar>functions</envar></entry> 
        <entry colname="col2">
         Points to the Zend function block, discussed in the preceding
         section.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><envar>module_startup_func</envar></entry> 
        <entry colname="col2">
         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 <literal>FAILURE</literal>; otherwise,
         <literal>SUCCESS</literal>. To mark this field as unused, use
         <literal>NULL</literal>. To declare a function, use the macro
         <literal>ZEND_MINIT</literal>.
        </entry> 
       </row> 
     <row> 
        <entry colname="col1"><envar>module_shutdown_func</envar></entry> 
        <entry colname="col2">
         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
         <function>module_startup_func</function>. To indicate a failure
         during deinitialization, return <literal>FAILURE</literal>;
         otherwise, <literal>SUCCESS</literal>. To mark this field as
         unused, use <literal>NULL</literal>. To declare a function, use
         the macro <literal>ZEND_MSHUTDOWN</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><envar>request_startup_func</envar></entry> 
        <entry colname="col2">
         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
         <literal>FAILURE</literal>; otherwise,
         <literal>SUCCESS</literal>. <emphasis>Note:</emphasis> 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
         <literal>NULL</literal>. To declare a function, use the macro
         <literal>ZEND_RINIT</literal>.
        </entry> 
     </row> 
       <row> 
        <entry colname="col1"><envar>request_shutdown_func</envar></entry> 
        <entry colname="col2">
         This function is called once after every page request and works
         as counterpart to <function>request_startup_func</function>. To
         indicate a failure here, return <literal>FAILURE</literal>;
         otherwise, <literal>SUCCESS</literal>.
         <emphasis>Note:</emphasis> 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 <literal>NULL</literal>. To declare a
         function, use the macro <literal>ZEND_RSHUTDOWN</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><envar>info_func</envar></entry> 
        <entry colname="col2">
         When <function>phpinfo</function> 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 <literal>NULL</literal>. To declare a function, use
         the macro <literal>ZEND_MINFO</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><envar>version</envar></entry> 
        <entry colname="col2">
         The version of the module. You can use
         <literal>NO_VERSION_YET</literal> 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): <literal>"2.5-dev"</literal>,
         <literal>"2.5RC1"</literal>, <literal>"2.5"</literal> or
         <literal>"2.5pl3"</literal>.
        </entry>
       </row> 
       <row> 
        <entry colname="col1">Remaining structure elements</entry>
        <entry colname="col2">
         These are used internally and can be prefilled by using the
         macro <literal>STANDARD_MODULE_PROPERTIES_EX</literal>. You
         should not assign any values to them. Use
         <literal>STANDARD_MODULE_PROPERTIES_EX</literal> only if you
         use global startup and shutdown functions; otherwise, use
         <literal>STANDARD_MODULE_PROPERTIES</literal> directly.
        </entry> 
       </row> 
      </tbody> 
     </tgroup> 
    </informaltable> 
   </example> 
   <para>
    In our example, this structure is implemented as follows: 
    <programlisting role="c">
<![CDATA[
zend_module_entry firstmod_module_entry =
{
    STANDARD_MODULE_HEADER,
    "First Module",
    firstmod_functions,
    NULL, NULL, NULL, NULL, NULL,
    NO_VERSION_YET,
    STANDARD_MODULE_PROPERTIES,
};
]]>
    </programlisting>
    This is basically the easiest and most minimal set of values you
    could ever use. The module name is set to <literal>First
     Module</literal>, then the function list is referenced, after which
    all startup and shutdown functions are marked as being unused.
   </para> 
   <para>
    For reference purposes, you can find a list of the macros involved
    in declared startup and shutdown functions in 
    <xref linkend="internals2.ze1.zendapi.tab.init-shutdown"/>. 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
    (<literal>INIT_FUNC_ARGS</literal> and
    <literal>SHUTDOWN_FUNC_ARGS</literal>), 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.
   </para> 
   <table xml:id="internals2.ze1.zendapi.tab.init-shutdown">
    <title>Macros to Declare Startup and Shutdown Functions</title> 
     <tgroup cols="2">
      <colspec colnum="1" colname="col1" colwidth="1.00*"/>
      <colspec colnum="2" colname="col2" colwidth="1.41*"/> 
      <tbody> 
       <row> 
        <entry colname="col1">Macro</entry> 
        <entry colname="col2">Description</entry> 
       </row> 
       <row> 
        <entry colname="col1"><literal>ZEND_MINIT(module)</literal></entry> 
        <entry colname="col2">
         Declares a function for module startup. The generated name will
         be <literal>zend_minit_&lt;module&gt;</literal> (for example,
         <literal>zend_minit_first_module</literal>).  Use in
         conjunction with <literal>ZEND_MINIT_FUNCTION</literal>.
        </entry> 
       </row> 
       <row> 
      <entry colname="col1"><literal>ZEND_MSHUTDOWN(module)</literal></entry> 
        <entry colname="col2">
         Declares a function for module shutdown. The generated name
         will be <literal>zend_mshutdown_&lt;module&gt;</literal> (for
         example, <literal>zend_mshutdown_first_module</literal>).  Use
         in conjunction with <literal>ZEND_MSHUTDOWN_FUNCTION</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><literal>ZEND_RINIT(module)</literal></entry> 
        <entry colname="col2">
         Declares a function for request startup. The generated name
         will be <literal>zend_rinit_&lt;module&gt;</literal> (for
         example, <literal>zend_rinit_first_module</literal>).  Use in
         conjunction with <literal>ZEND_RINIT_FUNCTION</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><literal>ZEND_RSHUTDOWN(module)</literal></entry> 
        <entry colname="col2">
         Declares a function for request shutdown. The generated name
         will be <literal>zend_rshutdown_&lt;module&gt;</literal> (for
         example, <literal>zend_rshutdown_first_module</literal>).  Use
         in conjunction with <literal>ZEND_RSHUTDOWN_FUNCTION</literal>.
        </entry> 
       </row> 
       <row> 
        <entry colname="col1"><literal>ZEND_MINFO(module)</literal></entry> 
        <entry colname="col2">
         Declares a function for printing module information, used when
         <function>phpinfo</function> is called. The generated name will
         be <literal>zend_info_&lt;module&gt;</literal> (for example,
         <literal>zend_info_first_module</literal>).  Use in conjunction
         with <literal>ZEND_MINFO_FUNCTION</literal>.
        </entry> 
       </row> 
      </tbody> 
     </tgroup> 
   </table> 
  </sect3> 
  
  <sect3 xml:id="internals2.ze1.zendapi.structure.get-module"> 
   <title>Creation of <function>get_module</function></title> 
   <para>
    This function is special to all dynamic loadable modules. Take a
    look at the creation via the <literal>ZEND_GET_MODULE</literal>
    macro first:
   </para>
   <programlisting role="c">
<![CDATA[
#if COMPILE_DL_FIRSTMOD
     ZEND_GET_MODULE(firstmod) 
#endif
]]>
   </programlisting> 
   <para>
    The function implementation is surrounded by a conditional
    compilation statement. This is needed since the function
    <function>get_module</function> is only required if your module is
    built as a dynamic extension. By specifying a definition of
    <literal>COMPILE_DL_FIRSTMOD</literal> 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 <function>get_module</function> is simply left
    out.
   </para> 
   <para>
    <function>get_module</function> is called by Zend at load time
    of the module. You can think of it as being invoked by the
    <function>dl</function> 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.
   </para> 
   <para>
    If you don't implement a <function>get_module</function> function in
    your dynamic loadable module, Zend will compliment you with an error message
    when trying to access it.
   </para> 
  </sect3> 

  <sect3 xml:id="internals2.ze1.zendapi.structure.implementation">
   <title>Implementation of All Exported Functions</title>
   <para>Implementing the exported functions is the final step. The
    example function in <literal>first_module</literal> looks like this: 
    <programlisting role="c">
<![CDATA[
ZEND_FUNCTION(first_module)
{
    long parameter;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &parameter) == FAILURE) {
        return;
    }

    RETURN_LONG(parameter);
}
]]>
    </programlisting>
    The function declaration is done
    using <literal>ZEND_FUNCTION</literal>, which corresponds
    to <literal>ZEND_FE</literal> in the function entry table (discussed
    earlier).
   </para> 
   <para>
    After the declaration, code for checking and retrieving the function's
    arguments, argument conversion, and return value generation follows (more on
    this later).
   </para> 
  </sect3> 
  
  <sect3 xml:id="internals2.ze1.zendapi.structure.summary"> 
   <title>Summary</title> 
   <para>
    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.
   </para> 
   <para>
    Now, in the following sections, read on about how to make use of PHP's
    internals to build powerful extensions.
   </para>
  </sect3>
 </sect2>
<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->