From: Ralph Mason Date: 2001-11-20T06:34:36+09:00 Subject: [ruby-talk:25864] Ruby and COM play nicely together. I have been putting together the other half of the ruby COM euqation allowing COM application to call ruby objects. And I have to tell you it's made COM the easiest and most fun it's ever been!!!! Imagine writing a complete DCOM server in 3 lines of code!! Imagine dynamicaly adding methods to com objects. Well with ruby you can, and when you mix it with com you can seamlessly call across as many languages as you like. Here is a my VB unit test for the ruby com layer I've done. It makes me smile just to look at it. ( a form with a ListBox, a Button and a Text Box ) Dim rbyObject As Object Private Sub Form_Load() 'RubyCom Test Harness Dim obj1 As Object Dim Obj2 As Object Dim WinClass As Object Dim MyClass As Object Set obj1 = CreateObject("Ruby.Myclass") obj1.x = 0 While (obj1.x < 1000) obj1.x = obj1.x + 1 Wend a (obj1.x = 1000) Set Obj2 = CreateObject("Ruby.Myclass") a (obj1.Type = Obj2.Type) ' Call inspect on each type a (obj1.Type Is Obj2.Type) ' Compare actual objects 'Test references & finding the same object Set WinClass = obj1.eval("WIN32OLE") Set MyClass = obj1.eval("Myclass") a (WinClass.Type = MyClass.Type) a (WinClass.Type Is MyClass.Type) a (Not (WinClass Is MyClass)) a (obj1.Type Is MyClass) a (Not (obj1.Type Is WinClass)) 'Test calling back to other com objects Using Properties obj1.x = Form1 a (obj1.instance_eval("@x.kind_of? WIN32OLE")) Form1.Caption = "" obj1.instance_eval ("@x.Caption='Test'") a (Form1.Caption = "Test") a (WinClass.IsKind_of(obj1.eval("Class"))) a (obj1.instance_eval("@x.Caption") = "Test") 'Test returned references obj1.x = Obj2 obj1.x.x = "Test" a (obj1.x.x = "Test") 'Test Is and Me and nil values obj1.instance_eval ("def makexnil! ; @x=nil ; end") a (Not obj1.x.IsNil) a (Not (obj1.x Is Nothing)) obj1.MakexnilMe a (obj1.x Is Nothing) a (Not obj1.IsNil) 'Check out [] and []= Set obj1 = obj1.eval("{}") obj1("1") = True obj1("2") = True a (obj1("1") And obj1("2")) a (obj1("3") Is Nothing) 'Test an array k = obj1.eval("[1,2,3,3,4,5,5,5]") a (k(0) = 1 And k(2) = 3 And k(4) = 4) a (UBound(k) = 7) obj1.instance_eval ("def a_test(x); x.uniq ; end") k = obj1.a_test(k) a (UBound(k) = 4) a (k(0) = 1 And k(2) = 3 And k(4) = 5) 'Test multiple args Set obj1 = obj1.instance_eval("Myclass.new()") a (obj1.test(1, "test", 59) = "1 test 59") 'Test Calling back from Ruby to a local object using method calls Set rbyObject = CreateObject("Ruby.Myclass") rbyObject.instance_eval ("def add(x); @y=0 if @y.nil? ; @x.additem('Rby ' +x + (@y+=1).to_s ); end") rbyObject.instance_eval ("def clear(); @x.Clear ; end") rbyObject.x = List1 'List1 is a VB listbox object rbyObject.Clear rbyObject.Add ("1") rbyObject.Add ("1") rbyObject.Add ("1") a (List1.ListCount = 3) rbyObject.Clear a (List1.ListCount = 0) 'Test Method Missing ( and function name conversion ) rbyObject.instance_eval ("def method_missing(x); x.id2name ; end ") a (rbyObject.empty = "empty") a (rbyObject.IsEmpty = "empty?") a (rbyObject.EmptyMe = "empty!") a (rbyObject.NoReallyEmptyMe = "noReallyEmpty!") a (rbyObject.xor_ = "^") a (rbyObject.and_ = "&") a (rbyObject.or_ = "|") a (rbyObject.plus_ = "+") a (rbyObject.minus_ = "-") a (rbyObject.times_ = "*") a (rbyObject.div_ = "/") a (rbyObject.mod_ = "%") a (rbyObject.greater_ = ">") a (rbyObject.less_ = "<") a (rbyObject.greatereql_ = ">=") a (rbyObject.lesseql_ = "<=") a (rbyObject.compare_ = "<=>") a (rbyObject.insert_ = "<<") a (rbyObject.extract_ = ">>") a (rbyObject.match_ = "~") rbyObject.instance_eval ("def ==(x); '==' ; end ") rbyObject.instance_eval ("def ===(x); '===' ; end ") rbyObject.instance_eval ("def =~(x); '=~' ; end ") a (rbyObject.eqleql_(1) = "==") a (rbyObject.eqleqleql_(1) = "===") a (rbyObject.eqlmatch_(1) = "=~") 'Call renamed method on a real class Set obj1 = obj1.eval("/regex/") a (obj1.eqlmatch_("regex") = 0) 'Setup for the button push test Set rbyObject = CreateObject("Ruby.Myclass") rbyObject.x = List1 rbyObject.instance_eval ("def add(x); @y=0 if @y.nil? ; @x.additem('Rby ' +x + (@y+=1).to_s ); end") End Sub Sub a(x As Boolean) If Not x Then MsgBox "Assertion Failed" Debug.Assert (False) End If End Sub Private Sub Command1_Click() rbyObject.Add Text1.Text End Sub And the simple rubyclass class Myclass def test2(x,y) [x,y] end def x=(y) @x = y end def x @x end def test(x,y,z) "#{x} #{y} #{z}" end end Now there is no excuse not to use ruby in your windows work. you can even do it without anyone knowing ;-) I plan on releasing this in the next couple of days. It only works with the VC build of ruby currently, this is not so much of a problem as ruby loads inprocess with you application as a DLL. You could also use the com surrogate process if you would rather keep it in it's own process space. Ralph