In all the code examples we have seen so far, there are 2 or 3 lines at the beginning of the program which look like the following:
/* here lies some code to link to the target object */ /* now, obj references a real object */ |
Now it's about time to try to replace these with some real code. This is where real magic lies :) The ORB is the secret repository of all this magic.
module CORBA { typedef string ORBid; typedef sequence <string> arg_list; ORB ORB_init (inout arg_list argv, in ORBid orb_identifier); interface ORB { string object_to_string (in Object obj); Object string_to_object (in string str); }; }; |
One of the first thing to do is to initialize the magic: the CORBA_ORB_init function must be called prior to anything else. The ORBit parameter must uniquely identify the ORB in environments where more than one ORB is running. We will use: "orbit-local-orb". This string is specific to each ORB implementation. For example, here is how we could use this function:
#include <orb/orbit.h> int main (int argc, char **argv) { CORBA_Object orb; CORBA_Environment ev; orb = CORBA_ORB_init (&argc, argv, "orbit-local-orb", &ev); }; |
However, it is obvious this will not work because the ev variable is not initialized. It should be initialized with a call to CORBA_exception_init(CORBA_Environment *ev). This call, specific to the C mapping, will be explained in this chapter's last part with exception handling. On the whole, this set of calls are complete magic: upon startup, the program has no Object reference and cannot call any method from any interface: that is why the CORBA_ORB_init function exists which does not need any Object parameter. It is a "bootstrap function of the core ORB".
Once the ORB is initialized, we would like to get our object reference to call its methods. To do so, it is possible to use CORBA naming service which associates to each registered object a human readable string but this is kept for chapter 3. Hopefully there is another simpler (i am not convinced IOR strings are simpler but... They are more basic. Less elegant for sure.) mechanism: IOR strings.
When you write the server object, you have to register this object in the ORB so that the ORB may generate object references to be used in clients. These object references contain all the necessary information to access the object: its location, etc... The ORB provides a mean to "serialize" these object references. That way, when you launch your server, it will register itself with the ORB. The ORB will give back a valid object reference. The server can serialize this reference in a file. The file may then be opened by the client and be used to get the object reference back.
This is achieved through the use of two CORBA::ORB methods: object_to_string and string_to_object. The server will call object_to_string and the client string_to_object. These strings are IOR strings and their structure depends on the protocol used, the kind of object... They are usually rather long (a few hundred characters).
Here is simple server code to generate the serialized file:
#include <orb/orbit.h> int main (int argc, char **argv) { CORBA_ORB orb; CORBA_Environment ev; CORBA_Object obj; FILE *file; CORBA_exception_init(&ev); orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); /* code to register the different methods */ /* this step results in getting a CORBA_Object, * obj, which contains the object reference */ if (!file = fopen ("object.ior", "w")) { fprintf (stderr, "error: could not open serializing file\n); exit (1); } fprintf (file, "%s", CORBA_ORB_object_to_string (orb, obj, &ev)); fclose (file); return 0; } |
Now, client code to invert the process
int main (int argc, char **argv) { CORBA_ORB orb; CORBA_Environment ev; CORBA_Object obj; FILE *file; /* rather long string: should be enough for all our needs :) */ char buffer[10000]; char *ior; CORBA_exception_init(&ev); orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev); if (!file = fopen ("object.ior", "r")) { fprintf (stderr, "error: could not open serializing file\n); exit (1); } fgets (buffer, 10000, file); ior = g_strdup (buffer); /* gets the raw string */ /* now, we have it finally !! */ obj = CORBA_ORB_string_to_object (orb, ior, &ev); /* now, it is possible to use this object reference * to call some of its methods */ fclose (file); return 0; } |
This code obviously assumes that client and server are started in the same directory on the same machine. We'll see later how to deal with the naming service so that we don't have to meddle with IOR strings.