私は、JavaアプリケーションのRuby実装をロードするために、JRuby(JRuby 1.5に含まれているJSR233インターフェイス経由)をJavaアプリケーションから使用しようとしています。JRubyから正しくタイプされたJavaインタフェースのRuby実装を取得するにはどうすればよいですか?
私のサンプル実装は次のようになります。
インタフェース:
package some.package;
import java.util.List;
public interface ScriptDemoIf {
int fibonacci(int d);
List<String> filterLength(List<String> source, int maxlen);
}
Rubyの実装:
require 'java'
include Java
class ScriptDemo
java_implements some.package.ScriptDemoIf
java_signature 'int fibonacci(int d)'
def fibonacci(d)
d < 2 ? d : fibonacci(d-1) + fibonacci(d-2)
end
java_signature 'List<String> filterLength(List<String> source, int maxlen)'
def filterLength(source, maxlen)
source.find_all { |str| str.length <= maxlen }
end
end
クラスローダー:
public ScriptDemoIf load(String filename) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("jruby");
FileReader script = new FileReader(filename);
try {
engine.eval(new FileReader(script));
} catch (FileNotFoundException e) {
throw new ScriptException("Failed to load " + filename);
}
return (ScriptDemoIf) m_engine.eval("ScriptDemo.new");
}
は、(明らかにローダがあります実生活では少し一般的です。実装クラス名が "ScriptDemo"であるとは想定されていません。これは単純化のためです)。
問題 - ローダーの最後の行でクラスキャスト例外が発生します。engine.eval()
は、RubyObject
タイプを返します。これは、自分のインターフェイスにうまくキャストできません。私がWeb上で読んだものから、私はRubyのセクションのuse point of use java_implements
がインターフェイスの実装が適切にコンパイルされているという印象を受けました。
私は間違っていますか?
ありがとうございます!本当に問題を解決しました。私の代わりの方法は、ローダに 'Object l = m_engine.eval(simpleName +" .new ");を実行させることでした。呼び出し可能なi =(呼び出し可能な)m_engine; return i.getInterface(l、ScriptDemoIf.class); 'これは醜いです... – Guss