Table of contents:

The examples provided in this section serve as a starting point for building or laying out larger extensions. By filling in your own code in the noted places, you can focus on the functional bits rather than worrying about formatting and other boring make-work.

All templates provided hereunless otherwise notedare neutrally named cookbook and should be changed to a more appropriate name when you implement them. In all instances, assume casing to be significantfor example, cookbook is not the same as COOKBOOK.


The material covered in this section is just a consolidated rehash of the core material covered in the body of this book. If you already feel familiar with it, skip down to the Code Pantry later in this appendix.


Minimal Extension

If you've been through more than a little of the book, this framework will look instantly familiar. It's the first extension you saw in Chapter 5, aptly named "Your First Extension."

The three files shown in Listings C.1, C.2, and C.3 represent the absolute least amount of code and configuration data necessary to build a loadable PHP extension. Refer back to Chapter 5 for a refresher on how to build this as a loadable module.

Listing C.1. config.m4A Simple Configuration Script

 [Whether to enable the "cookbook" extension],
 [ enable-cookbook Enable "cookbook" extension support])

if test $PHP_COOKBOOK != "no"; then
 PHP_NEW_EXTENSION(cookbook, cookbook.c, $ext_shared)

Listing C.2. php_cookbook.hA Simple Header File

#define PHP_COOKBOOK_EXTNAME "cookbook"
/* The value of this constant may be arbitrarily chosen by you.
 PHP does not actually use this value internally; however it
 makes sense to incrementally increase it with each release. */
#include "config.h"
#include "php.h"
extern zend_module_entry cookbook_module_entry;
#define phpext_cookbook_ptr &cookbook_module_entry

Listing C.3. cookbook.cA Simple Extension Source File

#include "php_cookbook.h"
zend_module_entry cookbook_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
 NULL, /* Functions */
 NULL, /* MINIT */
 NULL, /* RINIT */
 NULL, /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901

Extension Life Cycle Methods

Chapter 1, "The PHP Life Cycle," and many of the following chapters discussed the five phases engaged by PHP during the course of its execution: Startup, Activation, Runtime, Deactivation, and Shutdown.

During all but the Runtime phase, PHP activates an appropriate callback found in the zend_module_entry structure. Each of these methods can be left NULL and unused as in the minimal skeleton shown previously, or implemented independently using the appropriate naming and prototype macros. Under ordinary circumstances each method should return the SUCCESS constant. If a callback is unable to perform a vital task, it must return FAILURE so that PHP can raise the proper error and exit if necessary.

Add any or all of these functions as needed to any of the source files in your projectproviding they are visible to your zend_module_entry structure. Listing C.4 shows a set of minimal implementations for these callbacks.

Listing C.4. Declaring Life Cycle Callbacks

 /* Code placed here will be executed during the Startup phase
 Startup occurs when the PHP interpreter is first being initialized
 prior to entering any Activation phases
 The M in MINIT is for "Module" (a.k.a. Extension) Initialization */
 return SUCCESS;
 /* Code placed here will be executed during the Activation phase(s)
 Activation occurs just prior to the execution of each script request.
 The R in RINIT is for "Request" Initialization */
 return SUCCESS;
 /* Code placed here will be executed during the Deactivation phase(s)
 Deactivation occurs just after completion of a given script request. */
 return SUCCESS;
 /* Code placed here will be executed during the Shutdown phase
 Shutdown occurs after all requests have been processed and the SAPI
 is proceeding to unload. */
 return SUCCESS;

For each callback function added, replace the corresponding NULL entry (denoted by comments in Listing C.3) with the matching use macro (see Listing C.5).

Listing C.5. Adding Callback Macros to zend_module_entry

zend_module_entry cookbook_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
 NULL, /* Functions */
 PHP_MINIT(cookbook), /* MINIT */
 PHP_RINIT(cookbook), /* RINIT */
 NULL, /* MINFO */
#if ZEND_MODULE_API_NO >= 20010901

Declaring Module Info

To add extension-specific information to output generated by phpinfo();, add an MINFO callback function to your source file and place a matching macro into your zend_module_entry structure (see Listing C.6). Unlike the life cycle functions, the MINFO callback does not expect a return value.

Listing C.6. Declaring Module Information

 /* The following example will display a simple 2x2 table
 Refer to Chapter 12, "Startup, Shutdown, and a Few Points in Between"
 For more information on generating MINFO output */
 php_info_print_table_row(2, "Cookbook Module", "enabled");
 php_info_print_table_row(2, "version", PHP_COOKBOOK_EXTVER);

As with the life cycle callbacks, replace the NULL entry in your zend_module_entry structure corresponding to MINFO with: PHP_MINFO(cookbook).

Adding Functions

Internal implementations of userspace functions are declared to the engine using a vector of zend_function_entry structures as described in Chapter 5, "Your First Extension." Place the structure shown in Listing C.7 just above your zend_module_entry struct.

Listing C.7. Empty Function Entry List

zend_function_entry php_cookbook_functions[] = {
 /* Function entry macros such as
 PHP_FE(), PHP_FALIAS, and PHP_NAMED_FE() go here */

Now link that new structure into your module entry by replacing the NULL corresponding to the functions list with php_cookbook_functions.

After the zend_function_entry structure is in place, define actual function implementations using PHP_FUNCTION() macros such as shown in Listing C.8.

Listing C.8. Empty Function Declaration

 /* Code to be executed when cookbook_dosomething()
 is called from userspace goes here */

Now place a matching entry into your zend_function_entry structure prior to the terminating NULL entry: PHP_FE(cookbook_dosomething, NULL).

Adding Resources

PHP uses the resource data type to store opaque or complex data types that don't or can't map to PHP userspace data (see Listing C.9). These types are declared in the MINIT callback of an extension, which is called during the Startup phase. Refer to Chapter 9, "The Resource Data Type," for a detailed explanation of their use.

Listing C.9. Declaring a Resource Type

/* List Entry type IDs are registered in a common pool shared by all threads
 And therefore can be stored in a true-global scope */
int le_cookbook_type;

/* The name of your resource type may be arbitrarily assigned and
 does not necessarily have to be unique,
 although good practices dictate it should be. */
#define PHP_COOKBOOK_RESOURCE_NAME "Cookbook Resource"

/* Don't forget: Since MINIT is being used,
 it must be referenced from the zend_module_entry structure */
 le_cookbook_type = zend_register_list_destructors_ex(
 NULL, /* Non-persistent destructor */
 NULL, /* Persistent destructor */
 return SUCCESS;

When a resource variable is implicitly freed during the Deactivation phase or during the course of a request because it has been unset() or has fallen out of scope, its nonpersistent destructor is called. For persistent resources, explained in Chapter 9, the persistent destructor will also be called when the resource is removed from the persistent list, typically in response to an explicit close or shut down command.

The prototypes for both destructors are identical (see Listing C.10):

Listing C.10. Resource Destructor Callbacks

void php_cookbook_resource_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 /* The registered data to be destructed can be found in rsrc->ptr */

Once defined, the name of the destructor callback (php_cookbook_resource_dtor) can be added to the zend_register_list_destructors_ex() call in place of either or both of the NULL placeholders as appropriate.

Adding Objects

The simplest useful object declaration begins with a few lines in the MINIT callback and a declaration of at least one method (see Listing C.11).

Listing C.11. Adding Objects

 /* Code added here will be executed in response to calling
 Cookbook_Class::__construct(), including in response to
 new Cookbook_Class() which implicitly calls the constructor */

zend_function_entry php_cookbook_methods[] = {
 /* Refer to Chapter 11, "PHP5 Objects," for the meaning of
 the ZEND_ACC_* constants */
 PHP_ME(Cookbook_Class,__construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)

/* Don't forget: Because MINIT is being used,
 it must be referenced from the zend_module_entry structure */
 zend_class_entry ce;
 INIT_CLASS_ENTRY(ce, "Cookbook_Class", php_cookbook_methods);
 zend_register_internal_class(&ce TSRMLS_CC);

 return SUCCESS;

Code Pantry

The PHP Life Cycle

Variables from the Inside Out

Memory Management

Setting Up a Build Environment

Your First Extension

Returning Values

Accepting Parameters

Working with Arrays and HashTables

The Resource Data Type

PHP4 Objects

PHP5 Objects

Startup, Shutdown, and a Few Points in Between

INI Settings

Accessing Streams

Implementing Streams

Diverting the Stream

Configuration and Linking

Extension Generators

Setting Up a Host Environment

Advanced Embedding

Appendix A. A Zend API Reference

Appendix B. PHPAPI

Appendix C. Extending and Embedding Cookbook

Appendix D. Additional Resources

Extending and Embedding PHP
Extending and Embedding PHP
ISBN: 067232704X
EAN: 2147483647
Year: 2007
Pages: 175
Authors: Sara Golemon © 2008-2020.
If you may any questions please contact us: