3 ms·
JNI allows one to write C code that bridges the gap between the Java VM and existing C libraries. That C code must be compiled, and must follow some rather tedi
by cstrahan 3y ago
JNI allows one to write C code that bridges the gap between the Java VM and existing C libraries. That C code must be compiled, and must follow some rather tedious patterns (regarding method signatures and other little details). It’s a bit of a pain to write and compile, if all you want to do is quickly call some function from an existing C library.
Also, because symbol resolution is done at compile-time, this is a non starter for something like JRuby, wherein one would want to write plain Ruby code to call a C function — rather than writing Ruby, Java and JNI flavored C code. Ruby is an interpreted language, so calling into or out of C requires dynamic symbol resolution, and for the C->Ruby callback case, a closure must be created on the fly (that is, a C ABI function must be JIT compiled for that method or proc). This isn’t particular to Ruby — any interpreted language will run into this issue on the JVM (picture Python and its ctypes and/or cffi libraries).
You can see some of the hoops that JRuby had to jump through to support this use case, in order to provide a JRuby implementation of the ‘ffi’ gem interface:
https://javadoc.io/doc/org.jruby/jruby-core/9.2.13.0/org/jruby/ext/ffi/FFI.html https://javadoc.io/doc/org.jruby/jruby-core/9.2.13.0/org/jru...
https://www.igvita.com/2009/01/15/bridging-mri-jruby-rubinius-with-ffi/ https://www.igvita.com/2009/01/15/bridging-mri-jruby-rubiniu...
It’s been a minute, so my recollection may be wrong, but IIRC JRuby uses Java and JNI to call into a C shim that then calls into libffi to handle things like creating C ABI conforming closures and such on the fly (the ffi gem on CRuby also uses libffi for the same purposes).
Correction: I believe JRuby uses JNA, which in turn is Java+JNI to call C that then calls into libffi, which is then leveraged to call whatever other functions (or create C callbacks back into the JVM). So I’m pretty sure FFM would be an officially supported replacement (maybe superset?) of JNA. (I’m on vacation and typed all of this out on my phone, so forgive me if I got some details a bit off)
I’m pretty sure that just about all of that complexity can be ripped out once FFM is generally available.
- headius 3y agoYou know a lot about JRuby's use of FFI! One correction though, JRuby uses a reimplementation of jna called jnr, which is generally much faster (close to jni for simple calls). We are working with folks on the FFM team to re-implement the core jnr back end. It's very exciting work, and I will present it this weekend at RubyConf Taiwan!
- cstrahan 3y ago> You know a lot about JRuby's use of FFI! Back when IronRuby (the Ruby implementation for .NET) was still actively developed, I decided to work on a port of the ffi gem for it. The JRuby code base provided some great ideas, thus my familiarity (but that was well over a decade ago now — time flies and memories fade, haha). Sadly, I reached 100% test success rate the same week Jimmy Schementi announced his departure and the writing was on the wall for IronRuby and the other IronX languages, so I never released my work. Thanks for all you’ve done, btw! Your efforts and general enthusiasm definitely inspired me to dig into language implementation and other explorations. > One correction though, JRuby uses a reimplementation of jna called jnr, which is generally much faster (close to jni for simple calls). Thanks for the correction. I might have to take a look at JNR sometime! > We are working with folks on the FFM team to re-implement the core jnr back end. It's very exciting work, and I will present it this weekend at RubyConf Taiwan! That’s exciting news - I’ll keep an eye out for the talk once it’s available online.