[Rubydotnet-developer] Introduction
Status: Alpha
Brought to you by:
thomas
From: Tim S. <ti...@ih...> - 2003-07-17 22:47:34
|
A few days ago I posted a message to rubytalk mentioning a library I am working on for allowing Ruby and DotNet to call each others' methods (http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/75198) Since then I've been contacted by Ben Schroeder who told me about the similar project he has been working on, and who told me about this list. Status of my library: It mostly works, need to do more testing / documentation. (Well, write *any* documentation!) Ben's project has a richer interface e.g. uses Enumerable methods whenever a DotNet object supports Count (or Length) and get_Item. There are other things I'd like to implement like a "dotnet_methods" methods. I'll try to make a release soon under a BSD-ish license. My interface (calling DotNet methods from Ruby) looks like: # It would be nicer if this was # DotNet::System::Collections::Hashtable. hash_class = DotNet::Class.new('System.Collections.Hashtable') h = hash_class.new # h is an instance of DotNet::Instance h['a'] = [1, 2, 'three'] p(h['a']) # -> "[1, 2, \"three\"]" p(h.Count) # -> 1 # DotNet.new can be used just for type conversions. five = DotNet.new(5) # five is an instance of DotNet::Instance p(five.to_rb == 5) # -> true Type conversions: Integers, strings, arrays, nil, true, false are automatically converted to DotNet types. Calling 'to_rb' on a DotNet::Instance instance converts it to the Ruby type, if the object was one of the previously listed types. All operators/indexers are implemented (I believe). For relational operators (==, eql?, <, <=, >=, > ) we force the returned value to be a Ruby boolean. (Theoretically a DotNet library could implement '<' as returning e.g. an integer.) <=> is implemented using "== and <". == is implemented using Equals not op_Equality since e.g. System.Int32 only defines the former. I also implement "hash" in terms of "GetHash". When calling DotNet methods, if the method name ends in '=', we chop off the '=' and treat it as a SetField|SetProperty. Otherwise we use InvokeMethod|GetField|GetProperty. (My library uses GetType#InvokeMember.) At the moment I don't have any way to use DotNet delegates from the Ruby side. DotNet exceptions are mapped to DotNet::Exception Ruby exceptions, where 'message' is the same as the DotNet 'Message', and the 'dotnet_exception' attr_reader provides the original DotNet exception. From the DotNet (e.g. C#) side, I can do things like RbType a = RbType.Eval('[1, 2, 3]'); int size = a.Call("size").ToInteger(); There are (implicit operator) conversions for integers, strings, arrays, null, true, false. You can use a delegate to represent a Ruby block, although I haven't tested this. I've implemented most operators in the usual way, although I forgot to do indexers -> [] and []=. Ruby exceptions are mapped into DotNet RbException types. Implementation wise, the code for calling Ruby from DotNet and calling DotNet from Ruby are mostly separate. They each use reference counting, which has the known problems e.g. circular references. The code is implemented in C# and C (Ruby extension.) There are about 8 lines of Microsoft's Extended C++ to allow for initialisation. The code does not run on Mono yet (http://www.go-mono.com/) because of a couple of bugs in that implementation. I intend to support this on both Microsoft and Mono implementations of dotnet. I'd be interested in seeing what other people have developed so we can share ideas/code. |