C 言語は、非常に低レベルなレイヤーを今風に扱えるようにした言語です。 PHP のように組み込みでさまざまな機能が用意されているわけではありません。 リフレクションや動的モジュール読み込み、範囲チェック、 スレッドセーフなデータ管理、さまざまなデータ構造 (リンクリストやハッシュテーブルなど) は組み込みの機能としては用意されていません。 と同時に、C 言語はプログラミング言語としての一般的な機能はすべて兼ね備えています。 それなりに努力しさえすれば、先ほどあげた内容はすべて実現可能です。 実際、Zend Engine ではこれらをすべて利用することができます。
Zend API を、拡張しやすくかつわかりやすいものにするためにさまざまな努力を重ねてきました。 しかし、C 言語はどんな拡張に対しても何らかの宣言が必要となるものであり、 不慣れな人が見ると冗長に感じたり説明不足に感じたりすることは避けられません。 これから説明していくこれらの言語構造は、Zend Engine 2 や 3 においては "一度書いたらあとは忘れてしまってよい" ものです。 ここで示すのは、PHP 5.3 の ext_skel で生成したファイル php_counter.h および counter.c の抜粋です。どのような宣言が生成されるのかをごらんください。
注意: 勘のいい方ならお気づきでしょうが、 実際のファイルにはここであげた以外にもいくつかの宣言があります。 これらの宣言は Zend サブシステム群に固有のものであり、 ここで説明するのは適切ではありません。
extern zend_module_entry counter_module_entry; #define phpext_counter_ptr &counter_module_entry #ifdef PHP_WIN32 # define PHP_COUNTER_API __declspec(dllexport) #elif defined(__GNUC__) && __GNUC__ >= 4 # define PHP_COUNTER_API __attribute__ ((visibility("default"))) #else # define PHP_COUNTER_API #endif #ifdef ZTS #include "TSRM.h" #endif
#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" #include "php_counter.h" /* ... */ #ifdef COMPILE_DL_COUNTER ZEND_GET_MODULE(counter) #endif
PHP_COUNTER_API
は、PHP 以外の関数から使用するために宣言しているものです。
他のモジュールから使わせるためにエクスポートすることを想定しています。
counter 拡張モジュールではこれを宣言していないので、
最終版のヘッダファイルではこのマクロを取り除きます。
PHPAPI
マクロは完全に別の場所で宣言されており、
標準のモジュールが phpinfo()
関数を実行する際に使用します。
COMPILE_DL_COUNTER
が configure
で定義されるのは、counter 拡張モジュールが有効になっており、
かつ PHP への静的リンクではなく動的ロードモジュールとしてビルドする場合のみです。
ZEND_GET_MODULE
で定義するちょっとした関数を使用して、
Zend はその拡張モジュールの
zend_module_entry を実行時に取得します。
注意: counter モジュールを静的にビルドしようとして main/php_config.h を調べた人の中には
HAVE_COUNTER
という定数が定義されていることにお気づきのかたもおられるかもしれません。 この定数はソースコードのどこでも用いられていません。 理由は簡単で、このチェックは行われないからです。 このチェックは不要なのです。 拡張モジュールが有効になっていなければ、 そのファイルがコンパイル対象となることはないからです。