I have recently been working on a new project, called for the moment ruby+objc (I know I need a better name), and it's now time to write a little about it.
ruby+objc can be seen as a new flavor of Ruby that runs on the Objective-C runtime. It's basically a modified version of the existing Ruby 1.9 branch. This is something I wanted to do since a little less than 2 years now, but Ruby 1.8 was not suitable. And of course I didn't want to re-invent the wheel.
It basically behaves as the normal Ruby 1.9. For instance, all meaningful tests included in the 1.9 distribution are passing.
Speaking about the implementation, all Ruby classes are actually Objective-C classes, modulo some bits that need to be kept separately. To avoid conflicts, Objective-C class names are prefixed by RB. The same exists for existing Objective-C classes, that are imported into Ruby at demand.
As you can see, a Ruby String object is in fact an Objective-C object of the RBString class. And it responds to the -[NSObject description] method, which is evident since NSObject is now an ancestor of RBString.
(gdb) po [NSObject new]
<NSObject: 0x278080>
(gdb) po rb_ary_new3(1, 0x278080)
<RBArray: 0x19cd44>
(gdb) p ((struct RArray *)0x19cd44)->len
$4 = 1
Pure Objective-C objects can be passed into Ruby without any problem. As an example, we add a pure NSObject object into a Ruby array. (Note that the RBArray Objective-C object can be casted as an RArray C structure.)
But there is more.
(gdb) po [0x19cd44 last]
<NSObject: 0x278080>
Since Ruby classes are actually Objective-C classes, their methods are also exposed in Objective-C. Here, we call Array#last by sending the Objective-C last message to the object, and we get the same identical pure NSObject object that we created earlier.
(gdb) po rb_funcall(0x278080, rb_intern("to_s"), 0)
<RBString: 0x19cc80>
(gdb) p ((struct RString *)0x19cc80)->as.heap.ptr
$8 = 0x278520 "#<NSObject:0x278080>"
And reciprocally, we can call the Kernel#to_s method on our pure NSObject object, and it returns a valid Ruby string object. It works because the Kernel module is included in NSObject, and that the Objective-C methods are exposed in YARV.
That's enough for today, but to resume the big ideas, Ruby classes are Objective-C classes; methods are exposed in both languages; Ruby objects are Objective-C objects; and Objective-C objects can be used directly in Ruby. Proxy objects and caches are abolished! Everything is very straightforward, and according to a few micro-benchmarks that I made, it's around 10 times faster than RubyCocoa.
Stay tuned for more details, especially on garbage collection.