
		    Perl module for Ruby
			Version 0.2.7

		       Yoshida Masato


- 概要

Ruby から Perl を呼び出すためのモジュールです。Ruby と Perl 
を一緒にリンクするので，相性の問題でうまく動作しないこともあ
ります。

土岐さんの perllib (http://www.freedom.ne.jp/toki/ruby.html) 
の方がインストールが簡単で，しかも完成度が高いようです。


- インストール

Ruby-1.4.6 以降の使用をお勧めします。

あらかじめ，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のライセン
スのどちらかにしたがって利用することができます。


- 作者

 吉田正人 <yoshidam@inse.co.jp>, <yoshidam@yoshidam.net>


- 履歴

 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    最初のリリース
