Disclaimer: I’m really not a CORBA specialist. This article – and the others which may follow – only describe my understanding of the Ruby2CORBA bindings as I learn to use it. Moreover, what follows may be TAO-specific, since I don’t use CORBA extensively and I use the TAO corba implementation.
Ruby-side ORB initialization
First things first, we have to initialize a local ORB. This is done by
require 'corba'
options = { :orb_debuglevel => 0 }
orb_options = ["-ORBDebugLevel", options[:orb_debuglevel]]
orb = CORBA.ORB_init(orb_options, 'myORB')
(I personally don’t know if the ORB name (myORB here) is really important, if it
shoud be unique or whatever)
Connecting to the naming service
The easiest way is to use TAO’s multicast service discovery, which allows to set up the CORBA environment without any configuration. You will have to start the naming service by running
Naming_Service -m 1
in a shell (Debian users can also use this script at startup).
From the Ruby point of view, you need to generate the interface which allow us to
actually call the remote naming service. For that, get the CosNaming.idl IDL file,
which you can get from the ORB you use (for instance, with TAO development files).
This files describes describes the naming service interface from the CORBA point
of view. By running ridlc, the Ruby2CORBA IDL compiler, on it, you will get
a client (CosNamingC.rb) and server (CosNamingS.rb) file. We are
actually only interested by the client part: it allows us to actually call the
remote naming service as if it was a local object.
Then, in you ruby script, you can get a reference to the remote naming service by running
require 'CosNamingC'
ns = orb.resolve_initial_references('NameService')
If, for whatever reason you don’t want to use service discovery (or if service discovery does not work), you can use CORBA URIs:
Naming_Service -ORBListenEndpoints corbaloc:iior:0.0.0.0:2809
in which case you can get the name server from the ORB by directly referencing the IP of the host where the naming service runs (replace of course 192.168.52.141 by the real IP of the service on your network):
ns_loc = "corbaloc:iior:192.168.52.141:28209/NameServer"
ns = orb.string_to_object(ns_loc)
Finally, the TAO naming service allows to save the service IOR thanks to the -o option. You can then use
ns = orb.string_to_object(File.read(ior_file_path))
to connect – provided that you share a filesystem between the host where the naming service runs and the host where your script runs.
The returned object is actually untyped (for now): the Ruby side does not know what kind of methods you can call on it. To define that, you need to tell Ruby2CORBA that the naming service object is a NamingContextExt interface. You do that with
ns = CosNaming::NamingContextExt._narrow(ns)
Listing the available names
You can list the available toplevel bindings with
binding_list, binding_iterator = ns.list(limit)
where binding_list is an array of at most limit bindings, and binding_iterator
an interface which allows you to list the remaining bindings. From that point on,
you can iterate on these toplevel bindings by getting new NamingContext objects, by
using ns.resolve(binding_name). See this script for an
example of getting all the available names.
Resolving an object by name
Once you now the name of the object you really want, you simply get it from the toplevel naming context with
my_object = ns.resolve_str object_name
Alternatively, if the naming service is not compatible with the NamingContextExt interface,
but only with the NamingContext one (the TAO naming service is a NamingContextExt interface),
you have to build a CosNaming::Name object component by component. A Bla/Blo name has for
instance to be built with
object_name = CosNaming::Name.new
object_name[0] = CosNaming::NameComponent.new 'Bla', ''
object_name[1] = CosNaming::NameComponent.new 'Blo', ''
my_object = ns.resolve(object_name)
Some notes about Ruby2CORBA
If the name of a method on a CORBA interface clashes with an already existing Ruby one (for
instance the #id attribute of CosNaming::NameComponent objects, the Ruby2CORBA binding prefixes
it with r_. This can get a bit frustrating, but I do understand the rationale.
Ruby files generated by ridlc reference the source IDL. So, you have to make sure to have the IDL
files in your own Ruby libraries, and to ship this IDL along the Ruby core.