2016年6月26日日曜日

JavaからRubyスクリプトを実行する(JRuby)

2016/06/26 記事を投稿
JavaからRubyスクリプトを呼び出す方法をまとめる

環境

  • Eclipse Mars使用
  • Java 1.8
  • JRuby 9.1.2

準備

  • Eclipseでプロジェクトを作成しておく
  • JrubyのサイトからJRubyXXXComplete .jarをダウンロードしておく
    http://jruby.org/download
  • JRubyXXXComplete .jarを作成したプロジェクトのビルドパスに通しておく
    参考:http://goo.gl/mCkVEE

基本

Java側

// Scriptエンジンを生成
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("jruby");
// RubyスクリプトのFileReaderを準備
FileReader f = new FileReader("test.rb");
// Rubyスクリプトを評価
engine.eval(f);
// 関数呼び出し
obj = ((Invocable)engine).invokeFunction("test");

Ruby側

def test
 puts "Hello World"
end

これだけ。
Eclipse上で実行する場合はプロジェクト直下がカレントディレクトリとなるため、
プロジェクト直下にtest.rbを置いておけば実際にtest関数が呼ばれることが確認できる。

Rubyからの戻り値をJavaで使用する

engine.invokeFunction()の戻り値はObject型だが、Ruby側で返却した値がJavaの適切なクラスに変換されて入っている。それぞれが持つインスタンスメソッドなどはJavaDocを参照するといい。
Ruby側 → Java側
nil → null
文字列 → String
整数 → Long
実数 → Double
配列 → RubyArray ※List型に近い
ハッシュ → RubyHash ※Map型に近い
クラス → RubyObject

Rubyスクリプトから別のスクリプトをrequireする

通常、Rubyスクリプトを書く場合には複数のファイルに分け実装しrequireする。
結論から書くとJavaから呼び出す場合もほとんど書き方は変わらない。

コード

#別ファイルをrequire (./が無いとrequireできない点に注意)
require "./test2.rb"
def test
 puts "Hello World"
end

最初にengine.eval(f)するファイルはJavaから指定するが、それ以降はRubyファイル内で相対パスによってrequireできる。
"./"を書かない場合、おそらくカレントディレクトリがPATHに登録されていないため、ファイルを見つけることができない。

Ruby側で作成したインスタンスのメソッドを呼ぶ

Ruby側で生成したオブジェクトのインスタンスメソッドを呼び出す場合、
engine.invokeFunction()ではなくengine.invokeMethod()を使用する

コード

obj = inv.invokeFunction("関数名", "引数1", "引数2...");
inv.invokeMethod(obj, "インスタンスメソッド名", "引数1", "引数2...");

インスタンスメソッドを呼び出したいオブジェクトを第一引数に設定する

0 件のコメント:

コメントを投稿