拡張モジュールの構造
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_EXdeps フィールドを空のままにしておき、 開発者が使えるようにします。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 は、各リクエストの開始時にこれをコールします。 これは、可能な限り短くするか NULL にしておかなければなりません。 リクエストのたびにこれをコールするコストがかかるからです。
request_shutdown_func PHP_RSHUTDOWN(mymodule) コールバック関数です。Zend は、各リクエストの終了時にこれをコールします。 これは、可能な限り短くするか NULL にしておかなければなりません。 リクエストのたびにこれをコールするコストがかかるからです。
info_func PHP_MINFO(mymodule) コールバック関数です。Zend は、 phpinfo() 関数がコールされたときにこれをコールします。
version NO_VERSION_YET モジュールのバージョンを表す文字列。モジュールの作者が指定したものです。 バージョン番号の形式は、 version_compare() に対応したもの (たとえば "1.0.5-dev") か CVS や SVN のリビジョン番号 (たとえば "$Rev: 324071 $") にあわせたものにしておくことを推奨します。
globals_size [1] [4] [5] [6] sizeof(zend_mymodule_globals) このモジュール用のグローバル構造体が存在する場合のサイズ。
globals_id_ptr [1] [4] [5] [6] [7] &mymodule_globals_id 定数 USING_ZTSTRUE かどうかによって、 これらふたつのフィールドのうちのいずれかひとつだけが存在します。 最初のほうはモジュールのグローバル用の 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_ZTSTRUE のときだけです。
[8] このフィールドが存在するのは USING_ZTSFALSE のときだけです。
[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
};
/* }}} */

5.2 と 5.3 の違いは?

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


拡張モジュールの構造
PHP Manual