秋のPECLまつり

php_qr-0.3.1.tgz
php_yaml-0.1.1.tgz
php_senna-0.1.0.tgz -> php_senna-0.1.1.tgz (SenRecordsのイテレータとしてのふるまいを修正)
php_unichar-0.1.0.tgz
php_dcomplex-0.1.0.tgz -> php_dcomplex-0.1.1.tgz (テストケースを追加、他少々)
php_opendogs-0.6.0.tgz
php_continuation-0.1.0.tgz
php_session_hash-0.1.0.tgz


久々にSennaバインディングをアップデート。sf.jpで公開されているバージョンではなく、Subversionの開発版が必要です。開発版の取得に関してはSennaのダウンロードのページを見てください。
開発版で実装されている新しいAPI、ql APIをサポートしました。しかし、それだけでは開発版に付属する公式バインディングと被って面白くないのでOO専用、PHP4のサポートは廃し、PHP 5.1以降専用としました。本音を言えばZend APIがちゃんと整理されている5.2以降専用にしたいのですが、主要Linuxディストリビューションで未だにPHP 5.1.6を採用しているものもあるので。
従来のAPIに関してはbasic APIのみ残しています。大抵の用途はql APIの言語バインディングRDBMSバインディング (Tritonn or Ludia) で十分だし、PHPエクステンションとしてのadvanced APIはあまり必要ないかなと。新しいAPIの詳細は後述します。


また、個人的なPHPエクステンションの習作としての位置づけが強かったせいもあるのですが、機能が増えてコードも見づらくなっていたOpenDogsエクステンションを

  • Unicode (UTF-8) 関連ユーティリティ「Unichar」
  • 複素数演算エクステンション「DComplex」
  • その他ユーティリティ「OpenDogs」

の3パッケージに分割しました。


その他のものは新機能はなく、主にZTSモードのPHP 5.2.4でコンパイルでき、動作するように修正しています。
# CodeGen_PECLが生成するコードだとZTSモードのPHP 5.2ではスレッド終了処理中にSegmentation Fault等の致命的なエラーが発生します。これはspecファイルに<globals>を書いたときだけ起こる問題で、グローバル変数を開放する関数のシグネチャが異なるのが原因と思われます。
# グローバル変数の初期化関数は“今のところ”無問題だけど、後に備えてPHP 5.2から用意されたマクロPHP_GINIT_FUNCTION, PHP_GSHUTDOWN_FUNCTIONを使うべきでしょう。
# 5.2以前、5.1や4.4のZTSモードでは確認していませんし、たとえ動作しなくても対応する気はありません。非ZTSな5.1.6と4.4.7では動作確認しています。

新しいSennaの使い方

文面はSenna2.0がやってくる!からパクらせていただきました。
実際の使用例は配布物に含まれるexamples/ql_api.php,basic_api.phpを、問い合わせ言語Senna QLに関しては上記リンク先を見てください。


インストール方法はいつもの通りです。

phpize && ./configure --with-senna=/path/to/senna-cfg && make && sudo make install
SenDb SenDb::create(string $path[, int $flags[, int $encoding])

(スタティックメソッド)
$pathで与えられた新しいデータベースを作成し、対応するSenDbインスタンスを返します。失敗した場合にはSenExceptionをスローします。
$flagsにはテーブル名を管理するsymに対するflag情報を指定します。通常は0を指定してください。引数が省略された場合のデフォルト値は0です。
$encodingは、作成するデータベースでデフォルトで使用される文字エンコーディングを指定します。(現状では、問合せ言語にリテラルとして渡した文字列も全てここに指定したエンコーディングに従って解釈されます) 引数が省略された場合のデフォルト値はSEN_ENC_DEFAULTで、これはSennaをconfigureしたときのオプションによります。日本語の場合はSEN_ENC_EUCJP, SEN_ENC_UTF8, SEN_ENC_SJISのいずれかを指定することになります。

SenDb SenDb::open(string $path)

(スタティックメソッド)
$pathで与えられた既に作成済のデータベースを開き、 対応するSenDbインスタンスを返します。 失敗した場合はSenExceptionをスローします。

SenContext SenContext::open(SenDb $db[, int $flags])

(スタティックメソッド)
同一プロセス内にロードされたSenDbインスタンスに対して接続を行い、対応するSenContextインスタンスを返します。失敗した場合にはSenExceptionをスローします。
$flagsには、以下が指定できますが、デフォルトでSEN_CTX_USEQLが指定されるので通常は省略してください。

SEN_CTX_USEQL
問合せ言語の使用の有無 (現状では必須)
SEN_CTX_BATCHMODE
入力した式の評価結果の表示/非表示
SenContext SenContext::connect(string $host, int $port[, int $flags])

(スタティックメソッド)
$hostに対応するホストの、$portに対応するポート番号に対して接続を行い、対応するSenContextインスタンスを返します。失敗した場合にはSenExceptionをスローします。
$flagsには、SenContext::open()と同じものが指定できます。

bool SenContext::send(string $str[, int $flags])

(インスタンスメソッド)
文字列$strをインタープリタに評価させます。$flagには以下が指定できます。

SEN_CTX_MORE
式が終端していない (まだ続きがある) ことを示します。
string SenContext::recv(void)

(インスタンスメソッド)
SenContext::send()で与えた文字列をインタープリタが評価した結果として得られた出力を受け取ります。
C言語APIと異なり、SEN_CTX_MORE bitを気にかける必要はありません。(内部で全ての結果を受け取ってから結合して返します)

array SenContext::info_get(void)

(インスタンスメソッド)
SenContextに関する情報を取得します。

Unicharエクステンション

関数名から接頭辞od_がなくなり、unichr(), uniord(), unistr_decode_entity(), unorm_nfc() ...となったほか、configureのオプションが少し変わりました。

phpize && ./configure --enable-unichar --with-unichar-icu=/path/to/icu-config && make && sudo make install

Unicode正規化に加えて、0.5.0で追加したUnicodeブロック情報にも独自の怪しげなデータに代わってICUを使うようになりました。これらの機能が不要なら --without-unichar-icu としてください。

DComplexエクステンション

関数名の接頭辞od_がdcomplex_になりました。

phpize && ./configure --enable-dcomplex && make && sudo make install

PHP5ではDComplexオブジェクトも利用できます。DComplexオブジェクトは配列/文字列/整数/実数にキャストされたときの挙動も設定されており、ぶっちゃけ複素数演算ができることよりもCodeGen_PECLで作成できるものとは一味違ったエクステンションの実装例として価値があるような気がしています。


使用例:

<?php
$e = new DComplex(M_E);
$n = $e->pow(M_PI)->pow(DComplex::i());
var_dump((array)$n, (string)$n, (double)$n, (int)$n);
/*
array(4) {
  ["real"]=>float(-1)
  ["imag"]=>float(1.2246063538224E-16)
  ["abs"]=>float(1)
  ["arg"]=>float(3.1415926535898)
}
string(15) "-1+1.22461e-16i"
float(-1)
int(-1)
*/
$p = $n->add(new DComplex(1, 2))->rotate(M_PI_4);
var_dump((array)$p, (string)$p, (double)$p, (int)$p);
/*
array(4) {
  ["real"]=>float(-1.4142135623731)
  ["imag"]=>float(1.4142135623731)
  ["abs"]=>float(2)
  ["arg"]=>float(2.3561944901923)
}
string(17) "-1.41421+1.41421i"
float(-1.4142135623731)
int(-1)
*/

OpenDogsエクステンション

0.5.0から上記2大機能を抜いたものとなっています。
本当に実験的な機能しか残ってないです。
きっと今後も思いつきで変な機能が載っては、一般に使えそうなのは独立し、そうでないのが残って蠱毒の壺のような状態になるのでしょう。良い意味で。