2006 年 3 月 12 日 21 時 48 分

ファイルハンドルの tie


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


Perl 5.8 系の IO レイヤは、
ファイルハンドルの奥底で秘密裏に処理を行う。
5.6 系で同様のことをするためには、
ファイルハンドルに細工をするのが最も速い。
tie 関数を使えばそのようなことが実現できる。

tie の仕組みを使うには、
事前にファイルハンドルとしての動作を模倣する、
パッケージ(クラス)を用意する必要がある。

tie 関数に、ファイルハンドルとパッケージ名を渡せば、
内部でクラスのインスタンスが作成され、
ファイルハンドルに関連付けられる。

以降、ファイルハンドルに対する操作があれば、
インスタンスのメソッドが呼び出されるので、
独自のハンドラコードを書くことができるのだ。


さて、ファイルハンドルの tie 用のクラスは、
以下のような名前のメソッドを実装する必要がある。
代表的なものだけ書いてみよう。

TIEHANDLE, WRITE, PRINT, PRINTF, READ, READLINE, GETC

TIEHANDLE はクラスのコンストラクタとなる。
その他は、IO 関数に対応するメソッドだ。
第 1 引数がファイルハンドルではなく、
bless したクラスのリファレンスになる以外は、
元の関数と同じ引数で呼び出される。

例えば FakeHandle というクラスを書いたなら、
tie 関数を以下のように使えば良い。

tie(*HANDLE, 'FakeHandle');

tie は FakeHandle->TIEHANDLE を呼び出して、
インスタンスを作成し、HANDLE に関連づける。
tie は戻り値として TIEHANDLE の戻り値、
つまりインスタンスを返すが、通常それを使うことはない。

これで、HANDLE に対する IO 関数の呼び出しは、
クラスのメソッド呼び出しに変換される。
例えば、コードで以下のように呼び出すと、

print HANDLE 'A', 'B', 'C';

代わりにFakeHandle のメソッドが呼び出される。

$instance->PRINT('A', 'B', 'C');


例えば、スクリプトの最初に以下のようにすれば、
既存のコードに手を触れずに、標準出力への書き出しを
横取りすることができるというわけだ。

tie(*STDOUT, 'FakeHandle');



Copyright (c) 1994-2007 Project Loafer. All rights reserved.