From: Armin Roehrl Date: 2003-06-26T06:22:38+09:00 Subject: Re: Ruby/Java integration through JNI: working implementation You are a star!!! > > This is the idea that popped out during the last discussion in Euruko03. > (sorry, don't remember the name of the guy who exposed it :) > > It has taken me a little bit more than I first thought (the Chinese kept > me busy :), but 3 days later I have the first working code. > > I have created a straight-forward mapping for most of the > JNI API, which becomes available as a Ruby extension. This > allows the use of the low-level interface specified in > http://java.sun.com/products/jdk/1.2/docs/guide/jni/. This part is > written in C (around 4000 LOCs at the moment). > > I have built a simple reflection system that maps Java classes to Ruby > space, by using the reflection API to get information on all the > available > methods. At the moment it is written in Ruby but it should probably be > coded in C for speed (this can be done later w/o any problem) and allows > to call methods transparently as if they were implemented in Ruby. > > At the moment, the following is working: > * creating objects and manipulating native types > * static methods w/ arbitrary parameters and any return value (native or > object types) > * methods " " " " > * Java objects arrays * non virtual method calls > * method overloading (dispatching is performed depending on arg types) > * seamless conversion of Ruby String and Numeric types to the required > Java types according to method signatures > > Things I have to work on: > * think about Java exceptions: map them to Ruby or signal them somehow? > * dynamic definition of Java classes and adding native methods at > run-time (for instance to call Ruby Procs in callbacks) > * more automated conversions: Arrays to Java's type[] and vice-versa > * wrap Java's reflection API completely, providing convenient metaclass > abstractions & such > * add more methods to the wrapped Java objects to integrate them better > w/ Ruby > * cover more code w/ unit tests (esp. the reflection part) > > This is real example of what I'm doing: > > Given Simple.java: > > public class Simple { > public String doStuff(String a) { > return "I was called with argument \"" + a.toString() + "\"" ; > } > > public String doStuff(String a, String b) { > return a + b; > } > > public boolean compareStrings(String a, String b) { > System.out.println("I was passed " + a + " and " + b); > return a.equals(b); > } > > public int compare2(String a, String b) { > System.out.println("I was passed " + a + " and " + b); > return a.compareTo(b); > } > > public int sum(String a, String b) { > System.out.println("Adding " + a + " and " + b + " (inside Java!!!)"); > int i = Integer.parseInt(a) + Integer.parseInt(b); > System.out.println("The result will be: " + i); > return i; > } > } > > I can instantiate the Java object and access its methods from Ruby as > follows: > > require 'reflect' > require 'rjni' > > vm = RJNI::JVM.new "-cp ." > reflector = RJNI::Reflect.new(vm) > sclass = reflector["Simple"] > o = sclass.new_object > r = o.doStuff("foo passed from Ruby!!!!") > puts "Result: #{r}" > r = o.doStuff("hello, ", "world!") > puts "Result: #{r}" > r = o.compareStrings("ruby","matz") > puts "Result: #{r.to_b}" > r = o.compareStrings("matz","matz") > puts "Result: #{r.to_b}" > r = o.compare2("ruby","matz") > puts "Result: #{r.to_i}" > r = o.compare2("matz","matz") > puts "Result: #{r.to_i}" > r = o.sum("1", "1") > puts "Result: #{r.to_i}" > > Result: > > batsman@tux-chan:~/src/rjni$ > LD_LIBRARY_PATH=/usr/local/java/j2sdk1.4.1/jre/lib/i386/:/usr/local/java/j2sdk1.4.1/jre/lib/i386/client > > > ruby tc_reflect.rb > Result: I was called with argument "foo passed from Ruby!!!!" > Result: hello, world! > I was passed ruby and matz > Result: false > I was passed matz and matz > Result: true > I was passed ruby and matz > Result: 5 > I was passed matz and matz > Result: 0 > Adding 1 and 1 (inside Java!!!) > The result will be: 2 > Result: 2 > > > The code is right now in a state of flux as I am quickly adding > functionality but I am going through quite fast so I should be able to > release something soon. > -- -A. ---------------------------------------- Armin Roehrl, http://www.approximity.com We manage risk