I’ve been playing with the JRuby Direct Embedding and a lot of my
current work relies on passing Ruby blocks to a Java process that will
run them using the JRuby runtime.
I’m seeing some NPEs in what it seems to be very simple Ruby blocks. For
example the following will fail:
RubyInstanceConfig config = new RubyInstanceConfig();
config.setCompatVersion(CompatVersion.RUBY1_9);
runtime = Ruby.newInstance(config);
evaluator = JavaEmbedUtils.newRuntimeAdapter();
threadContext = ThreadContext.newContext(runtime);
RubyProc proc = (RubyProc)eval(“proc { puts ‘Hello World’ }”);
proc.getBlock().call(threadContext);
While a more complex example like the next one below, works:
// Parameters
RubyFixnum a = new RubyFixnum(runtime, 40);
RubyFixnum b = new RubyFixnum(runtime, 2);
RubyProc proc = (RubyProc)eval(“proc { |a, b| a + b }”);
Integer result = (Integer) proc.getBlock().call(threadContext, a,
b).toJava(Integer.class);
assertEquals(42, result.intValue());
Yet, a similar example concatenating strings fails:
RubyString a = RubyString.newString(runtime, "Hello ");
RubyString b = RubyString.newString(runtime, “World”);
RubyProc proc = (RubyProc)eval(“proc { |a, b| a + b }”);
String result = proc.getBlock().call(threadContext, a,
b).asJavaString();
assertEquals(“Hello World”, result);
But again, more esoteric examples like eval-ing a class in Ruby,
creating an instance and then passing it to another ruby proc works:
RubyObject param = (RubyObject)eval(“class Foo; def bar; ‘foobar’; end;
end; Foo.new”);
IRubyObject[] args = { param };
RubyProc proc = (RubyProc)eval("->(x;obj) { x }");
RubyObject result = (RubyObject) proc.getBlock().call(threadContext,
args);
String val = result.callMethod(“bar”).asJavaString();
assertEquals(val, “foobar”);
But if I try to invoke a method of the passed parameter it fails:
RubyObject param = (RubyObject)eval(“class Foo; def bar; ‘foobar’; end;
end; Foo.new”);
RubyProc proc = (RubyProc)eval(“proc { |obj| obj.bar }”);
RubyObject result = (RubyObject) proc.getBlock().call(threadContext,
param);
String val = result.asJavaString();
assertEquals(val, “foobar”);
So, it seems that if I try to do anything to/with the passed parameters
things go bananas, and as you can see in some of the examples above
calling puts on anything, event a literal string blows chunks.
I’m attaching a Maven project with a JUnit
test that shows the problems that I’m running into in case anyone is
interested. Of course, there is always the possibility that I’m doing
something supremely stupid.
Thanks,
Brian