■2006-02-08
* [Per][メモ] XSモジュールのSTDERRをキャプチャする
変数内部を覗くに便利なDevel::Peek。問答無用でSTDERRに出力されます(perl内部のルーチン経由)。このSTDERRに出力されたデータを別ハンドルにリダイレクトしようとして知ったのですが、open my $fh, '>', \$var; *STDERR = $fh
みたいな方法ではXSモジュールのSTDOUTやSTDERRをリダイレクトできないんですね(PerlIOを経由しないからかしら?)(→追記:PerlIO経由のみなら大丈夫であることをコメント欄で教えていただきました)。例えばIO::Captureを使って
use IO::Capture::Stderr; my $capture = IO::Capture::Stderr->new(); $capture->start(); Dump("a"); # STDERRに出力される…… print STDERR "foo!"; $capture->stop(); print "stderr : ", $capture->read;
とやっても、foo!しか取得できません。それでpipeとforkを使って子プロセスにDevel::Peek::Dumpを実行させ、パイプ経由で親プロセスが出力を回収するモジュールを書いたのですが、CPANにはIO::CaptureOutputというモジュールがありました。このモジュールは一時ファイルを利用してサブプロセスやXSモジュールのSTDOUT, STDERRを変数にキャプチャします。
このモジュールを(そのままでは不都合があるので)少し弄くってつくったDevel::Peek::Capture。Devel::Peekと同じDumpがインポートされます。
use Devel::Peek::Capture; my $foo = {}; my $output = Dump($foo); print $output;
おまけで、ある変数が threads::shared
で共有化されているかどうかを判定する is_shared
がついてます。
PerlIO経由だけであれば、一時ファイルがなくともできますね。<br><br>use Devel::Peek;<br>my $stderr; close STDERR;<br>open STDERR, ">", \$stderr or die $!;<br>Dump {Foo=>1, Bar=>2};<br>print "stderr:{$stderr}\n"'
あ、ほんとだ。<br>簡単なデバッグ用ならこっちの方で良いですね。