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 は、各リクエストの開始時にこれをコールします。
これは、可能な限り短くするか 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_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 キーワードだけです。