拡張モジュールの構造
PHP マニュアル

zend_module 構造体

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

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

Example#1 example 拡張モジュールにおける zend_module の宣言部

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

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

Example#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);
    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_EXdeps フィールドを空のままにしておき、 開発者が使えるようにします。name から version までのすべてのフィールドは、開発者が設定する必要があります。 その後、STANDARD_MODULE_PROPERTIES マクロで構造体の残りのフィールドを埋めます。あるいは STANDARD_MODULE_PROPERTIES_EX マクロを使用すると、 extension global と post-deactivation function のフィールドを空のままにします。 いまどきの拡張モジュールのほとんどは、モジュールグローバルを使用します。

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

モジュール構造体のフィールドの値
フィールド 説明
size footnote

このフィールドは、モジュール開発者が使うものではありません。

/footnote footnote

このフィールドは STANDARD_MODULE_HEADER_EX が設定します。

/footnote footnote

このフィールドは STANDARD_MODULE_HEADER が設定します。

/footnote
sizeof(zend_module_entry) この構造体の大きさ (バイト数)。
zend_api footnoteref footnoteref footnoteref ZEND_MODULE_API_NO モジュールをコンパイルした Zend API のバージョン。
zend_debug footnoteref footnoteref footnoteref ZEND_DEBUG モジュールがデバッグモードでコンパイルされていることを示すフラグ。
zts footnoteref footnoteref footnoteref USING_ZTS モジュールが ZTS (TSRM) を有効にしてコンパイルされていることを示すフラグ (メモリ管理 を参照ください)。
ini_entry footnoteref footnoteref NULL このポインタは Zend の内部で用い、 モジュールで宣言した非ローカルの INI エントリへの参照を保持します。
deps footnoteref 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$") にあわせたものにしておくことを推奨します。
globals_size footnoteref footnote

このフィールドは STANDARD_MODULE_PROPERTIES が設定します。

/footnote footnote

このフィールドは NO_MODULE_GLOBALS が設定します。

/footnote footnote

このフィールドは PHP_MODULE_GLOBALS が設定します。

/footnote
sizeof(zend_mymodule_globals) このモジュール用のグローバル構造体が存在する場合のサイズ。
globals_id_ptr footnoteref footnoteref footnoteref footnoteref footnote

このフィールドが存在するのは USING_ZTSTRUE のときだけです。

/footnote
&mymodule_globals_id 定数 USING_ZTSTRUE かどうかによって、 これらふたつのフィールドのうちのいずれかひとつだけが存在します。 最初のほうはモジュールのグローバル用の TSRM アロケーションテーブルへのインデックス、 後のほうはグローバルへの直接のポインタとなります。
globals_ptr footnoteref footnoteref footnoteref footnoteref footnote

このフィールドが存在するのは USING_ZTSFALSE のときだけです。

/footnote
&mymodule_globals
globals_ctor footnoteref footnoteref footnoteref PHP_GINIT(mymodule) この関数は module_startup_func前に コールされ、モジュールのグローバルを初期化します。
globals_dtor footnoteref footnoteref footnoteref PHP_GSHUTDOWN(mymodule) この関数は module_shutdown_func後に コールされ、モジュールのグローバルを破棄します。
post_deactivate_func footnoteref ZEND_MODULE_POST_ZEND_DEACTIVATE_N(mymodule) この関数は、リクエストの終了処理の後で Zend からコールされます。 めったに使われることはありません。
module_started footnoteref footnote

このフィールドは STANDARD_MODULE_PROPERTIES_EX が設定します。

/footnote footnoteref
0 これらのフィールドは、Zend の内部管理用の情報を扱うために使用します。
type footnoteref footnoteref footnoteref 0
handle footnoteref footnoteref footnoteref NULL
module_number footnoteref footnoteref footnoteref 0

構造体の設定の実例

これだけ多くのフィールドがあると、 どれが何のためのものなのかがなかなかわかりにくいものです。 ここで、実際のサンプル拡張モジュールにおける zend_module の定義を見てみましょう。 この拡張モジュールは、カウンタ機能を提供するものです。 カウンタの現在値を取得する関数がコールされるたびに、カウンタの値がひとつ増えます。 カウンタをリセットする方法については INI スイッチで制御します。 なんだか実際にはあまり役に立たなさそうですが、 拡張モジュールの作成時に使用するテクニックをたくさん紹介するためにこうしています。

Example#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
};
/* }}} */

拡張モジュールの構造
PHP マニュアル