2011-01-06 23 views
0

我想从Java应用程序中使用JRuby(通过JRuby 1.5中包含的JSR233接口)加载Java接口的ruby实现。如何从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类型,这种类型不能很好地转换到我的界面。从我在网上阅读的东西中,我得到的印象是Ruby部分中使用的全部使用点java_implements是为了适当地编译接口实现。

我在做什么错?

回答

2

它应该是,但不幸的是,这种方式尚未完全接通。目前,#java_implements#java_signature仅用于创建基于Ruby类的Java源文件的jrubyc --java命令。您可能要考虑将其用于Ruby集成。

我们正在寻找这个例子来为未来的预编译脚本和运行时执行的脚本工作。如果您希望此脚本按预期工作,请尝试使用include Java::some.package.ScriptDemoIf而不是java_implements

+0

谢谢!那确实解决了这个问题。我的替代方法是让加载器执行'Object l = m_engine.eval(simpleName +“.new”);不可调用i =(可调用)m_engine;返回i.getInterface(l,ScriptDemoIf.class);`这很丑陋... – Guss 2011-01-06 18:38:18

相关问题