Perl module for Ruby Version 0.2.9 Yoshida Masato = 概要 Ruby から Perl を呼び出すためのモジュールです。Ruby と Perl を一緒にリンクするので,相性の問題でうまく動作しないこともあ ります。 = インストール Ruby-1.6.4 以降の使用をお勧めします。 あらかじめ,Perl をインストールしておく必要があります。Perl 5.005_03 で動作確認しています。 -Dusethreads な Perl でも動作するはずですが,モジュール内で Thread を使ったときに何が起きるか分かりません。 Perl と Ruby が同じ malloc を使っていることを確認して下さい。 Perl をコンパイルするときに ./Configure -dse -D d_dosuid -Uusemymalloc のようにして Perl 付属の malloc は使わないように設定して下さ い。さもないと非常に不安定になってしまいます。 あとは通常のモジュールインストールを行ってください。動的リン クに対応している場合は以下の通りです。 ruby extconf.rb make make install Linux2.0.36+libc5,Solaris2.5.1/SPARC,Solaris2.6/SPARC, Solaris7/Intel で動作することを確認していますが,ライブラリ の相性などで,どうしても不安定なときは Ruby と静的にリンクす ると安定することがあります。 Perl 本体を共有ライブラリ化している場合,libperl.so のロード に失敗する OS も存在するようです。その場合, 以下のように --with-libperl オプションで共有ライブラリを指定してください。 ruby extconf.rb --with-libperl=/usr/lib/libperl.so Perl 側から Ruby の関数を呼びたい場合は Perl に Ruby モジュー ル for Perl をインストールして下さい。このモジュールは Ruby の中の Perl でしか動作しません。動的リンク可能な処理系でなけ ればインストールできないでしょう。 cd Ruby perl Makefile.PL make make install = 使い方 Ruby の make 時に静的にリンクしていない場合は, require "perl" としてから使用してください。 以下のように Perl オブジェクトを生成し,eval, call 等で Perl のコードを実行します。 perl = Perl.new("-e", "0") perl.eval("$a = 100") ret = perl.get_sv("a") == Perl -> Ruby データ型変換 Perl#eval, Perl#call, Perl#get_sv, PerlObject#send, PerlObject#call, PerlObject#[], PerlObject#value などのス カラーの戻値は Perl から Ruby へのデータ型変換が行なわれま す。Perl のオブジェクト型データは参照の形で Ruby 側で保持 可能です。 Perl 型 Ruby 型 -------------------------- undef nil IV (整数) Integer NV (実数) Float PV (文字列) String RV (参照) PerlObject 戻値がスカラーでない場合は Ruby で受け取れないので,必ず最 終結果がスカラーになるようにして下さい。 例 ary = perl.eval('(1, 2, 3)') -> 整数 3 しか受け取れない ary = perl.eval('[1, 2, 3]') -> 配列の参照が PerlObject として受け取れる == Ruby -> Perl データ型変換 Perl#call, PerlObject#send, PerlObject#call, PerlObject#[]= などの引数は Ruby から Perl へのデータ型変換が行なわれま す。 Ruby 型 Perl 型 ----------------------------------------- nil undef Fixnum IV (整数) Float NV (実数) String PV (文字列) Array RV to AV (配列の参照) Hash RV to HV (ハッシュの参照) PerlObject RV (参照) その他 文字列に変換 配列,ハッシュの要素も上記ルールの通りに再帰的に変換されま す。 Perl のハッシュはキーが文字列のみなので,Ruby のハッシュの キーを文字列に変換して用います。そのため,Ruby のハッシュ の 完全な写像にはなりません。 例 Ruby の {1=>'a', '1'=>'b'} は Perl では{'1'=>'a'} か {'1'=>'b'} のどちらかになります。 注意 Perl の関数で一見ハッシュを渡しているように見える関数が ありますが,実体は単なるリストです。Ruby から呼び出す場 合はリストで渡して下さい。また,Perl では引用符を省略し た文字列が許されますが,Ruby から呼び出す場合は引用符で 囲って下さい。 Perl: func1(A=>1, B=>2); Ruby: perl.call('func1', 'A', 1, 'B', 2) ハッシュの参照を渡したい場合は Ruby のハッシュが使えます。 Perl: func1({A=>1, B=>2}); Ruby: perl.call('func1', {'A'=>1, 'B'=>2}) == Perl クラス Perl インタプリタクラスです。複数のインスタンスを作成しよ うとすると PerlError 例外が発生します。 Object クラスの send メソッドを呼び出したい場合は "send_" メソッドを使って下さい。 === 特異メソッド new(...) Perl オブジェクトを生成します。引数として,Perl のコマ ンドラインを指定できます。引数を省略すると ("-e", "0") を指定した場合と同じになります。 実行エラーが起きたときは PerlError 例外が発生します。 例 perl_obj = Perl.new("-MIO::Handle", "-e", "0"); === メソッド eval(str) str を Perl のプログラムとして評価します。最後に評価さ れたスカラー値を返します。 スカラーコンテキストで評価されます。リストコンテキスト で評価したい場合は,[] で囲むなどして下さい。 str に Ruby のメタ文字等を含む場合は '' や %q// を使う ほうが安全でしょう。 eval はスコープを作るので,eval 内で宣言した my 変数の スコープはeval 内です。また,package 宣言も eval 内の み有効です。 エラーが発生したときは実行を中断し,例外 PerlError を 発生します。 例 input = perl_obj.eval("join('', @{[<>]})") perl_obj.eval(%q! print "Hello\n" !) call(func, ...) Perl 関数 func を実行します。残りの引数は Perl のオブ ジェクトに変換されて func に渡されます。 関数の戻値を返します。 エラーが発生したときは実行を中断し,例外 PerlError を 発生します。 例 perl_obj.eval("sub test { $_[0] + $_[1] }") ret = perl_obj.call("test", 1, 2) send(class, method, ...) Perl のクラス class の メソッド method を呼び出します。 残りの引数は Perl のオブジェクトに変換されてメソッドに 渡されます。 メソッドの戻値を返します。 存在しないクラスや,存在しないメソッドを呼び出したりす ると,例外も発生せずにプログラムが終了してしまいます。 メソッド内でエラーが発生したときは実行を中断し,例外 PerlError を発生します。 例 obj = perl_obj.send("IO::Handle", "new") get_sv(name) Perl のスカラー変数の内容を得ます。 変数名の頭の '$' は不要です。 例 perl_obj.eval("$var = 123") var = perl_obj.get_sv("var") == PerlObject クラス Perl の参照型のラッパオブジェクトです。 PerlObject オブジェクトは Perl オブジェクトが生きている間 だけ有効です。 Object クラスの send メソッドを呼び出したい場合は "send_" メソッドを使って下さい。 === メソッド 下記メソッドおよび Object クラスから継承したメソッド以外 が指定された場合,Perl のメソッドを呼び出そうとします。 メソッド名が衝突している場合は send メソッドで明示的に Perl のメソッドを呼び出すこともできます。 send(methodName, ...) bless された オブジェクトのメソッドを呼び出します。 残りの引数は Perl のオブジェクトに変換されてメソッドに 渡されます。 メソッドの戻値を返します。 オブジェクトが bless されてなかったり,存在しないメソッ ドを呼び出したりすると,例外も発生せずにプログラムが終 了してしまいます。 メソッド内でエラーが起きた場合は例外 PerlError が発生 します。 例 obj = perl.send('Class', 'new') ## 以下の 2 行は同等です。 obj.send('method', 1) obj.method(1) call(...) 関数オブジェクトを実行します。引数は Perl のオブジェク トに変換されて関数の引数になります。 関数の戻値を返します。 オブジェクトが関数オブジェクトではなかったり,関数内で エラーが起きた場合は例外 PerlError が発生します。 value 参照を解決して値を得ます。値がスカラーで無いときは値が 得られません。関数オブジェクトは call で,配列やハッ シュは [], to_a, to_hash で値を得て下さい。 参照でないときは例外 TypeError が発生します。 to_s 値を文字列に変換して得ます。値がスカラーでないときはデー タ型名とポインタ値が得られるかも知れません。 to_i 値を整数に変換して得ます。値がスカラーでないときはポイ ンタ値が得られるかも知れません。 to_f 値を実数に変換して得ます。値がスカラーでないときはポイ ンタ値が得られるかも知れません。 to_a 値が配列のときは配列に展開して返します。要素は再帰的に は展開されません。 bless された配列も単なる配列に展開されます。 値が配列でないときは値を唯一の要素とする配列を返します。 to_hash 値がハッシュのときはハッシュに展開して返します。要素は 再帰的には展開されません。 bless されたハッシュも単なるハッシュに展開されます。 値がハッシュでないときは例外 TypeError が発生します。 [] 値が配列のときは整数で指定されたインデックスで,ハッシュ のときは文字列で指定されたキーで指定された値を得ます。 bless された配列,ハッシュも同様です。 それ以外のときは例外 TypeError が発生します。 []= 値が配列のときは整数で指定されたインデックスで,ハッシュ のときは文字列で指定されたキーで指定された値を設定します。 値は Perl の型に変換されます。 bless された配列,ハッシュも同様です。 それ以外のときは例外 TypeError が発生します。 == Ruby for Perl モジュール Perl の中から Ruby の関数をコールバックするためのモジュー ルです。オブジェクトの寿命の管理が難しいので Ruby のオブジェ クトを Perl 側に保持する手段は提供されません。必ず Perl の データ型に変換されます。 use Ruby とするか,Perl オブジェクトを作るときに "-MRuby" 引数を渡してから使って下さい。 例 perl = Perl("-MRuby", "-e", "0") def hello(n) print "Hello, #{n}\n" end perl.eval(%q! Ruby::call("hello", "world"); !) === 関数 Ruby::eval(str) str を Ruby のプログラムとして評価します。最後に評価さ れた式を Perl のデータに変換して返します。 実行エラーが起きたときは Ruby 側で例外が発生して Perl には戻りません。 戻値の型変換は以下の通り。 Ruby 型 Perl 型 ----------------------------------------- nil undef Fixnum IV (整数) Bignum 文字列に変換 Float NV (実数) String PV (文字列) Array RV to AV (配列の参照) Hash RV to HV (ハッシュの参照) その他 オブジェクト識別子を文字列に変換 Ruby::call(func, ...) func を Ruby の関数として呼び出します。残りの引数は Ruby のデータに変換されて func に渡されます。 関数の戻値を Ruby::eval と同様に Perl のデータに変換し て返します。 実行エラーが起きたときは Ruby 側で例外が発生して Perl には戻りません。 引数の型変換は以下の通り。 Perl 型 Ruby 型 -------------------------- undef nil IV (整数) Integer NV (実数) Float PV (文字列) String その他 文字列に変換 Ruby::send(oid, method, ...) オブジェクト識別子 oid で表される Ruby オブジェクトの メソッド method を呼び出します。残りの引数は Ruby::call と同様に Ruby のデータに変換されて func に 渡されます。 関数の戻値を Ruby::eval と同様に Perl のデータに変換し て返します。 oid が不正な場合の動作は保証されません。 実行エラーが起きたときは Ruby 側で例外が発生して Perl には戻りません。 Ruby::call は以下の呼び出しと同等です。 sub call { my $func = shift; my $obj = Ruby::eval("Object"); Ruby::send($obj, $func, @_); } = バグ Perl で #define MYMALLOC になっていると,GC のタイミングなど で落ちてしまうことがあります。必ず Ruby と同じ malloc を使っ て下さい。 Perl#send, PerlObject#send で存在しないメソッドを呼び出す と,Ruby 側にエラーを返さずにプログラムが終了してしまいます。 = 権利 本拡張モジュールの著作権は吉田正人が保持します。 本拡張モジュールは,Ruby のライセンス,またはPerlのライセン スのどちらかにしたがって利用することができます。 = 作者 吉田正人 = 履歴 Nov 14, 2001 version 0.2.9 Perl 5.6.x の -Dusethreads に対応 Jun 11, 2001 version 0.2.8 Ruby 1.6.4 用に Makefile.PL 修正 (Akinori -Aki- MUSHA さんありがとうございます) Sep 15, 2000 version 0.2.7 Ruby 1.6.0 対応 Sep 14, 2000 version 0.2.6 Perl 5.6.0 対応, FreeBSD 対応 (Akinori -Aki- MUSHA さんありがとうございます) Mar 8, 1999 version 0.2.5 Ruby-1.3.1 に対応 Dec 26, 1998 version 0.2.4 missing_method 経由で呼び出され るメソッドでの例外でメソッド名 が表示されるように変更 perl_call_* 時のテンポラリ引数, 戻値の後始末を追加 Dec 16, 1998 version 0.2.3 Perl#send 追加 Dec 3, 1998 version 0.2.2 大きい整数の扱いを修正 Dec 2, 1998 version 0.2.1 XS モジュールに Ruby::send 追加 Nov 27, 1998 version 0.2 データアクセスメソッドなど大幅改造 Nov 18, 1998 version 0.1 最初のリリース