基本構造
拡張モジュールのグローバル変数
拡張モジュールの構造
PHP Manual

## zend_module 構造体

PHP 拡張モジュールのソースファイルの中には、 C プログラマにとって目新しいものがいくつか含まれています。 これらの中でも最も重要であり、 拡張モジュールを開発するにあたって最初にさわることになるのが zend_module 構造体です。 この構造体には豊富な情報が格納されており、 その拡張モジュールの依存性やバージョン、コールバック、 その他重要なデータを Zend Engine に伝える役割を果たします。 この構造体の中身は、何度も大幅に変更されています。 ここでは、PHP 5.2 の時点の情報をもとにして説明します。 PHP 5.3 では少々変更されている点もあります。

counter.c での zend_module の宣言は、次のようになります。これは、 ext_skel --extname=counter で生成したものをもとにして、既に存在しないいくつかの構造体を削除したものです。

例1 counter 拡張モジュールにおける zend_module の宣言部

    /* {{{ counter_module_entry
     */
    zend_module_entry counter_module_entry = {
        STANDARD_MODULE_HEADER,
        "counter",
        counter_functions,
        PHP_MINIT(counter),
        PHP_MSHUTDOWN(counter),
        PHP_RINIT(counter),        /* Replace with NULL if there's nothing to do at request start */
        PHP_RSHUTDOWN(counter),    /* Replace with NULL if there's nothing to do at request end */
        PHP_MINFO(counter),
        "0.1", /* Replace with version number for your extension */
        STANDARD_MODULE_PROPERTIES
    };
    /* }}} */

最初はちょっとひるむかも知れませんが、 大半の部分はよく見れば非常に単純です。 次に示すのは、PHP 5.3 の zend_modules.h における zend_module の宣言部です。

例2 PHP 5.3 における zend_module の定義

    struct _zend_module_entry {
        unsigned short size;
        unsigned int zend_api;
        unsigned char zend_debug;
        unsigned char zts;
        const struct _zend_ini_entry *ini_entry;
        const struct _zend_module_dep *deps;
        const char *name;
        const struct _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);
        const char *version;
        size_t globals_size;
    #ifdef ZTS
        ts_rsrc_id* globals_id_ptr;
    #else
        void* globals_ptr;
    #endif
        void (*globals_ctor)(void *global TSRMLS_DC);
        void (*globals_dtor)(void *global TSRMLS_DC);
        int (*post_deactivate_func)(void);
        int module_started;
        unsigned char type;
        void *handle;
        int module_number;
    };

これらのフィールドの多くは、決して拡張モジュールの作者が触ることはありません。 数多くのマクロが標準で用意されており、 そのマクロが適切な値を自動的に設定します。 `STANDARD_MODULE_HEADER` マクロは、 deps フィールドまでのすべての内容を埋めます。 一方 `STANDARD_MODULE_HEADER_EX` は deps フィールドを空のままにしておき、 開発者が使えるようにします。name から version までのすべてのフィールドは、開発者が設定する必要があります。 その後、`STANDARD_MODULE_PROPERTIES` マクロで構造体の残りのフィールドを埋めます。あるいは `STANDARD_MODULE_PROPERTIES_EX` マクロを使用すると、 extension global と post-deactivation function のフィールドを空のままにします。 いまどきの拡張モジュールのほとんどは、モジュールグローバルを使用します。

> 注意: ショートカットマクロに頼らず、構造体のフィールドをすべて自分で設定したい場合は、 この表の値を使用します。 これはお勧めしません。 そのフィールドの "正しい" 値は変わる可能性があります。 可能な限りマクロを使用するようにしましょう。

モジュール構造体のフィールドの値
フィールド | 値 | 説明
--- | --- | ---
size [1] [2] [3] | `sizeof(zend_module_entry)` | この構造体の大きさ (バイト数)。
zend_api [1] [2] [3] | `ZEND_MODULE_API_NO` | モジュールをコンパイルした Zend API のバージョン。
zend_debug [1] [2] [3] | `ZEND_DEBUG` | モジュールがデバッグモードでコンパイルされていることを示すフラグ。
zts [1] [2] [3] | `USING_ZTS` | モジュールが ZTS (TSRM) を有効にしてコンパイルされていることを示すフラグ (メモリ管理 を参照ください)。
ini_entry [1] [3] | `NULL` | このポインタは Zend の内部で用い、 モジュールで宣言した非ローカルの INI エントリへの参照を保持します。
deps [3] | `NULL` | モジュールの依存性一覧へのポインタ。
name | "mymodule" | モジュールの名前。これは "spl" あるいは "standard" のような短い名前です。
functions | mymodule_functions | モジュールの関数テーブルへのポインタ。 Zend は、これを使用してモジュール内の関数をユーザ空間に公開します。
module_startup_func | PHP_MINIT(mymodule) | コールバック関数です。Zend は、特定の PHP インスタンスで そのモジュールが最初にロードされるときにこれをコールします。
module_shutdown_func | PHP_MSHUTDOWN(mymodule) | コールバック関数です。Zend は、特定の PHP インスタンスから そのモジュールがアンロードされるとき (通常は最後のシャットダウン時) にこれをコールします。
request_startup_func | PHP_RINIT(mymodule) | コールバック関数です。Zend は、各リクエストの開始時にこれをコールします。
request_shutdown_func | PHP_RSHUTDOWN(mymodule) | コールバック関数です。Zend は、各リクエストの終了時にこれをコールします。
info_func | PHP_MINFO(mymodule) | コールバック関数です。Zend は、phpinfo() 関数がコールされたときにこれをコールします。
version | `NO_VERSION_YET` | モジュールのバージョンを表す文字列。モジュールの作者が指定したものです。 バージョン番号の形式は、 version_compare() に対応したもの (たとえば "1.0.5-dev") か CVS や SVN のリビジョン番号 (たとえば "$Rev: 283941 $") にあわせたものにしておくことを推奨します。
globals_size [1] [4] [5] [6] | sizeof(zend_mymodule_globals) | このモジュール用のグローバル構造体が存在する場合のサイズ。
globals_id_ptr [1] [4] [5] [6] [7] | &mymodule_globals_id | 定数 `USING_ZTS` が `TRUE` かどうかによって、 これらふたつのフィールドのうちのいずれかひとつだけが存在します。 最初のほうはモジュールのグローバル用の TSRM アロケーションテーブルへのインデックス、 後のほうはグローバルへの直接のポインタとなります。
globals_ptr [1] [4] [5] [6] [8] | &mymodule_globals
globals_ctor [4] [5] [6] | PHP_GINIT(mymodule) | この関数は module_startup_func の 前に コールされ、モジュールのグローバルを初期化します。
globals_dtor [4] [5] [6] | PHP_GSHUTDOWN(mymodule) | この関数は module_shutdown_func の 後に コールされ、モジュールのグローバルを破棄します。
post_deactivate_func [4] | ZEND_MODULE_POST_ZEND_DEACTIVATE_N(mymodule) | この関数は、リクエストの終了処理の後で Zend からコールされます。 めったに使われることはありません。
module_started [1] [9] [4] | 0 | これらのフィールドは、Zend の内部管理用の情報を扱うために使用します。
type [1] [9] [4] | 0
handle [1] [9] [4] | `NULL`
module_number [1] [9] [4] | 0
[1] このフィールドは、モジュール開発者が使うものではありません。 [2] このフィールドは `STANDARD_MODULE_HEADER_EX` が設定します。 [3] このフィールドは `STANDARD_MODULE_HEADER` が設定します。 [4] このフィールドは `STANDARD_MODULE_PROPERTIES` が設定します。 [5] このフィールドは `NO_MODULE_GLOBALS` が設定します。 [6] このフィールドは `PHP_MODULE_GLOBALS` が設定します。 [7] このフィールドが存在するのは `USING_ZTS` が `TRUE` のときだけです。 [8] このフィールドが存在するのは `USING_ZTS` が `FALSE` のときだけです。 [9] このフィールドは `STANDARD_MODULE_PROPERTIES_EX` が設定します。

### 構造体の設定の実例

これだけ多くのフィールドがあると、 どれが何のためのものなのかがなかなかわかりにくいものです。 ここで、サンプルの "counter" 拡張モジュールにおける zend_module の定義の最終形を見てみましょう。

例3 Counter 拡張モジュールの定義

    /* {{{ counter_module_entry
     */
    zend_module_entry counter_module_entry = {
        STANDARD_MODULE_HEADER,
        "counter",
        counter_functions,
        PHP_MINIT(counter),
        PHP_MSHUTDOWN(counter),
        PHP_RINIT(counter),
        PHP_RSHUTDOWN(counter),
        PHP_MINFO(counter),
        NO_VERSION_YET,
        PHP_MODULE_GLOBALS(counter),
        PHP_GINIT(counter),
        PHP_GSHUTDOWN(counter),
        NULL,
        STANDARD_MODULE_PROPERTIES_EX
    };
    /* }}} */

- このモジュールは他の何にも依存していないので、 `STANDARD_MODULE_HEADER` を使用します。
- "counter" がこの拡張モジュールの名前で、 このモジュールが Zend に渡すさまざまなコールバック関数の名前がこれをもとに決まります。 "counter" は、モジュール、グローバル、そしてリクエスト単位の 初期化関数とシャットダウン関数を使用し、phpinfo() 用の情報も提供します。したがって、7 つのコールバックをすべて定義することになります。
- モジュール定義を含むファイルの前のほうには zend_function_entry * 型の変数 counter_functions が定義されているはずです。 この部分では、そのモジュールがユーザに公開する関数の一覧が見られます。
- `NO_VERSION_YET` は、そのモジュールにバージョンがないことを Zend に教えてあげるうまいやりかたです。実際に使用するモジュールの場合は、 この部分には "1.0" などを入れることになるでしょう。
- "counter" はモジュール単位のグローバル変数を使用するので、 `PHP_MODULE_GLOBALS` を使用しています。
- このモジュールには後処理後の関数がないので、`NULL` を指定しています。
- このモジュールはグローバル変数を 使う ので、 構造体の最後には `STANDARD_MODULE_PROPERTIES_EX` を使用しています。

### 5.2 と 5.3 の違いは?

何もありません。 PHP 5.2 と PHP 5.3 での zend_module 構造体の唯一の違いは、いくつかの const キーワードだけです。

基本構造
拡張モジュールのグローバル変数
拡張モジュールの構造
PHP Manual