2011-01-06 1 views
0

私は、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がインターフェイスの実装が適切にコンパイルされているという印象を受けました。

私は間違っていますか?

答えて

2

それはすべきですが、あいにく未だに結構です。今のところ#java_implements#java_signatureは、Rubyクラスに基づいてJavaソースファイルを作成するコマンドjrubyc --javaによってのみ使用されます。 Rubyの統合にこれを使用することを検討してください。

この例は、将来コンパイルされたスクリプトと実行時に実行されるスクリプトの両方で動作することを目指しています。代わりに、このスクリプトを意図したとおりに動作させたい場合は、java_implementsの代わりにinclude Java::some.package.ScriptDemoIfを使用してみてください。

+0

ありがとうございます!本当に問題を解決しました。私の代わりの方法は、ローダに 'Object l = m_engine.eval(simpleName +" .new ");を実行させることでした。呼び出し可能なi =(呼び出し可能な)m_engine; return i.getInterface(l、ScriptDemoIf.class); 'これは醜いです... – Guss

関連する問題