ACE+TAO Opensource Programming Notes/Create a client
Discussion
[edit | edit source]So, unlike the server, the client doesn't involve implementing any code generated by the IDL. In the client, we simply instantiate a copy of the factory (using as an address the IOR string we generated with the server) and call its functions. This is all it takes for a basic client.
In the following code, the first argument to the program gets used as the address argument to TAO's orb to find our server. We are using the string generated earlier much like someone would use an IP address/port combination to find a host and application on the internet. While we will discuss it later, this analogy is somewhat apt because, on the internet, we usually prefer to use host names (using DNS) and well known services (ports) to access our services. In CORBA land, the same is true, and we will be discussing that later.
After acquiring the factory object from the orb, we then downcast the generic object to our My_Factory_var object as generated by the IDL. Note that we aren't downcasting it to "My_Factory", but rather "My_Factory_var". TAO, and perhaps CORBA seem to have adopted a standard of using XXX (as defined in your IDL) as the class you use to manipulate the ORB, and XXX_var (as generated by the IDL) as the repository for your object, as generated by XXX.
Now that you have generated your application specific factory object from the generic one received from the ORB, you may proceed to use these two objects as you would any normal C++ object. Just remember to keep in mind the type of data you are getting back from your queries, and or what type of data you are sending. Suffice it to say that inattention to these details will cause memory leaks.
Finally, destroy the ORB. While this is quite a simple application, and technically the destructor isn't needed, its still a good idea to get in the practice as leaving these objects hanging will cause all sorts of problems with distributed programs.
main.cpp
[edit | edit source]#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <iostream>
#include <cstdlib>
#include "ace_serviceI.h"
#include "ace_serviceC.h"
using namespace std;
using namespace CORBA;
int main(int argc, char *argv[])
{
// initialize the ORB
ORB_var orb = ORB_init (argc, argv, "whatever");
// There must be at least two arguments, the first is the factory
// name, the rest are the names of the stock symbols we want to
// get quotes for.
if (argc < 3) {
cerr << "Usage: " << argv[0]
<< " Factory_IOR symbol symbol..." << endl;
return 1;
}
// Bring in the IOR
Object_var factory_object = orb->string_to_object (argv[1]);
// Now downcast the object reference
My_Factory_var factory =
My_Factory::_narrow (factory_object.in ());
// Now get the full name and price of the other arguments:
for (int i = 2; i != argc; ++i) {
// Get the stock object
Widget_var widget =
factory->get_widget (argv[i]);
// Get its name, put it on a _var so it is automatically
// released!
String_var full_name = widget->full_name ();
// Now get the price
Double price = widget->price ();
cout << "The price of a widget in \""
<< full_name.in () << "\" is $"
<< price << endl;
}
// Destroy the ORB
orb->destroy ();
return EXIT_SUCCESS;
}
ace_service.idl
[edit | edit source]// Forward declare interface Widget; interface My_Factory { // = TITLE // A factory class for the widget interfaces // // = DESCRIPTION // Return the Widget interfaces based on their names // Widget get_widget (in string widget_name); }; interface Widget { // = TITLE // A simple interface to query the name and price of a widget // // = DESCRIPTION // Return the price and name of a single widget // readonly attribute string full_name; // Get the name. double price (); // Get the price };