Бих искал възможността да връщам блокове от вграден екземпляр на jruby към обикновена java. Моят Java код трябва да може да предава необходимите параметри (да приемем, че знае правилната арност) и след това да получава резултата. Всички проби ще бъдат оценени.
Как да върна Jruby proc/block/closure в java и да го извикам
Отговори (1)
Ако можете да направите директно вграждане, използвайте JavaEmbedUtils и или извикайте eval на низ от ruby код, който дефинира вашия proc/block/closure, или накарайте вашия ruby код да реализира интерфейс, където определени методи връщат вашия proc/block/closure. Невероятно измислен пример за сумиране на две числа по-долу:
SampleApp.java
import org.jruby.Ruby;
import org.jruby.RubyRuntimeAdapter;
import org.jruby.RubyFixnum;
import org.jruby.RubyProc;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import java.util.ArrayList;
class SampleApp {
public static void main(String[] args) {
// Create runtime instance
Ruby runtime = JavaEmbedUtils.initialize(new ArrayList());
// Parameters
RubyFixnum paramA = new RubyFixnum(runtime, 1);
RubyFixnum paramB = new RubyFixnum(runtime, 2);
// Runtime eval method
RubyRuntimeAdapter evaler = JavaEmbedUtils.newRuntimeAdapter();
RubyProc additionProcFromEval = (RubyProc)evaler.eval(runtime, "Proc.new { |a, b| a + b }");
printProcResult(runtime, additionProcFromEval, paramA, paramB);
// Interface implementation method
SomeInterfaceImpl someImpl = new SomeInterfaceImpl();
RubyProc additionProcFromInterface = (RubyProc)someImpl.getAdditionProc();
printProcResult(runtime, additionProcFromInterface, paramA, paramB);
// Shutdown and terminate instance
JavaEmbedUtils.terminate(runtime);
}
protected static void printProcResult(Ruby runtime, RubyProc proc, RubyFixnum paramA, RubyFixnum paramB) {
Block block = proc.getBlock();
ThreadContext threadContext = ThreadContext.newContext(runtime);
int result = (Integer)block.call(threadContext, paramA, paramB).toJava(new Integer(0).getClass());
System.out.println("Result = " + result);
}
}
SomeInterface.java
interface SomeInterface {
org.jruby.RubyProc getAdditionProc();
}
SomeInterfaceImpl.rb
require 'java'
class SomeInterfaceImpl
include Java::SomeInterface
java_signature 'org.jruby.RubyProc getAdditionProc()'
def getAdditionProc()
return Proc.new { |a, b| a + b }
end
end
И ето как можете да тествате:
javac -classpath jruby.jar SomeInterface.java
jrubyc --javac -cp . SomeInterfaceImpl.rb
javac -cp jruby.jar:. SampleApp.java
java -cp jruby.jar:. SampleApp
Препратки:
https://github.com/jruby/jruby/wiki/DirectJRubyEmbedding
http://tommy.chheng.com/2010/06/20/call-a-jruby-method-from-java/
person
marzagao
schedule
11.09.2011
Благодаря за усилията, но вие сте направили някои предположения, като например да приемете, че proc е съвместим с java интерфейс. Търсех нещо по-динамично без лепилото. Надявах се, че средата за изпълнение предостави помощник или нещо, което уви Proc в някакъв Java обект с var args като java.lang.refl.Method.invoke() просто работи..
- person mP.; 11.09.2011