1

我正在试验 Java 脚本引擎和 Ruby,但在 ruby​​ 脚本中设置一些实例变量时遇到了麻烦。这可能是我对 Ruby 缺乏了解,或者我对如何在脚本引擎中使用 ruby​​ 类缺乏了解。使用以下代码:

public class App {

    public static void main( String[] args ) throws Exception{
        ScriptEngineManager sm = new ScriptEngineManager();
        ScriptEngine se = sm.getEngineByName("jruby");

        StringBuilder sb = new StringBuilder();
        sb.append("class Test\n");
        sb.append("   attr_accessor :a, :b\n");
        sb.append("   def str\n");
        sb.append("      \"#{a}, #{b} is a test.\"\n");
        sb.append("   end\n");
        sb.append("end\n");
        sb.append("o = Test.new\n");

        Object o = se.eval(sb.toString());  

        se.put("@a", "A");
        se.put("@b", "B");

        System.out.println( ((Invocable) se).invokeMethod(o, "str"));
    }
}

我希望输出是'A,B是一个测试'

相反,输出是“,是一个测试”。

我应该如何在这段代码中设置变量 a、b?

编辑:为了清楚起见,理想情况下,我不想通过将变量附加到这个 StringBuilder 来设置它们——这只是为了说明。在实践中,我将从某个源加载脚本,然后想在该 Ruby 对象上设置属性和调用方法。我确定我只是错过了其他人都知道的一些关键步骤:)。感谢 Gareth Davis 的回答,我发现我可以成功使用绑定和全局变量,但这不适用于所有脚本。非常感谢任何超越“hello world”类型用法的好文章的链接,因为我没有找到任何像样的文章。

第二次编辑:这是工作的最终代码,我知道必须缺少关键行:)-

public class App {

    public static void main( String[] args ) throws Exception{

        //Must set this property if you want to call eval multiple times!
        System.setProperty("org.jruby.embed.localvariable.behavior", "persistent");
        ScriptEngineManager sm = new ScriptEngineManager();
        ScriptEngine se = sm.getEngineByName("jruby");

        StringBuilder sb = new StringBuilder();
        sb.append("class Test\n");
        sb.append("   attr_accessor :a, :b\n");
        sb.append("   def str\n");
        sb.append("      \"#{a}, #{b} is a test.\"\n");
        sb.append("   end\n");
        sb.append("end\n");
        sb.append("o = Test.new\n");

        Object o = se.eval(sb.toString());

        se.eval("o.a = \"A\"");
        se.eval("o.b = \"B\"");

        System.out.println( ((Invocable) se).invokeMethod(o, "str"));
    }
}
4

1 回答 1

1

那不会那样工作的。设置 a 和 b 值的唯一方法是计算o.a = 'A'o.b = 'B'

第一个解决方案是修改脚本以填充这些值:

    sb.append("o.a = 'A'\n");
    sb.append("o.b = 'B'\n");
    sb.append("o");
    Object o = se.eval(sb.toString());

我在 github.com 上创建了一个工作示例

与问题保持一致,可以使用以下内容(归功于@Mick Sear):

System.setProperty("org.jruby.embed.localvariable.behavior", "persistent"); 

// .. snip

Object o = se.eval(sb.toString());

se.eval("o.a = 'A'");
se.eval("o.b = 'B'");

System.out.println( ((Invocable) se).invokeMethod(o, "str"));
于 2012-05-21T21:50:32.363 回答