The Interface Definition Language (IDL) is a descriptive language (not a programming language) to describe the interfaces being implemented by the remote objects. Within IDL, you define the name of the interface, the names of each of the attributes and methods, and so forth. Once you've created the IDL file, you can use an IDL compiler to generate the client stub file and the server skeleton file in the C++ programming language.
The code sample below shows how the IDL compiler generates two client files, example_c.hh and
example_c.cc from the example that follows. These two files provide an
example class that the client uses. By convention, files generated by the IDL compiler always have either a
.cc or an
.hh suffix to make them easy to distinguish from files that you create yourself. If you wish, you can alter the convention to produce files with a different suffix.
class example : public virtual CORBA_Object {
protected:
example() {}
example(const example&) {}
public:
virtual ~example() {}
static const CORBA::TypeInfo *_desc();
virtual const CORBA::TypeInfo *_type_info() const;
virtual void *_safe_narrow(const CORBA::TypeInfo& ) const;
static CORBA::Object*_factory();
example_ptr _this();
static example_ptr _duplicate(example_ptr _obj) { /* . . . */ }
static example_ptr _nil() { /* . . . */ }
static example_ptr _narrow(CORBA::Object* _obj);
static example_ptr _clone(example_ptr _obj) { /* . . . */ }
static example_ptr _bind(
const char *_object_name = NULL,
const char *_host_name = NULL,
const CORBA::BindOptions* _opt = NULL,
CORBA::ORB_ptr _orb = NULL);
static example_ptr _bind(
const char *_poa_name,
const CORBA::OctetSequence& _id,
const char *_host_name = NULL,
const CORBA::BindOptions* _opt = NULL,
CORBA::ORB_ptr _orb = NULL);
virtual CORBA::Long
op1(
CORBA::Char _x, CORBA::Short_out _y);
};
The code sample above shows the op1 method generated by the IDL complier, along with several other methods. The
op1 method is called a
stub because when your client program invokes it, it actually packages the interface request and arguments into a message, sends the message to the object implementation, waits for a response, decodes the response, and returns the results to your program.
Since the example class is derived from the
CORBA::Object class, several inherited methods are available for your use.
The IDL compiler also generates a class named example_var, which you can use instead of an
example_ptr. The
example_var class will automatically manage the memory associated with the dynamically allocated object reference. When the
example_var object is deleted, the object associated with
example_ptr is released. When an
example_var object is assigned a new value, the old object reference pointed to by
example_ptr is released after the assignment takes place. A casting operator is also provided to allow you to assign an
example_var to a type
example_ptr.
class example_var : public CORBA::_var {
. . .
public:
static example_ptr _duplicate(example_ptr);
static void _release(example_ptr);
example_var();
example_var(example_ptr);
example_var(const example_var &);
~
example_var();
example_var& operator=(example_ptr);
example_var& operator=(const example_var& _var) { /* . . . */ }
operator example* () const { return _ptr; }
. . .
};
The code sample below shows how the IDL compiler generates two server files: example_s.hh and
example_s.cc. These two files provide a
POA_example class that the server uses to derive an implementation class. The
POA_example class is derived from the
PortableServer_ServantBase class.
class POA_example : public virtual PortableServer_ServantBase {
protected:
POA_example() {}
virtual
~POA_example() {}
public:
static const CORBA::TypeInfo _skel_info;
virtual const CORBA::TypeInfo *_type_info() const;
example_ptr _this();
virtual void *_safe_narrow(const CORBA::TypeInfo& ) const;
static POA_example * _narrow(PortableServer_ServantBase *_obj);
// The following operations need to be implemented
virtual CORBA::Long
op1(CORBA::Char _x, CORBA::Short_out _y) = 0;
// Skeleton Operations implemented automatically
static void _op1(void *_obj, CORBA::MarshalInBuffer &_istrm,
const char *_oper, VISReplyHandler& handler);
};
Notice that the op1 method declared in the IDL specification below is generated, along with an
_op1 method. The
POA_example class declares a pure virtual method named
op1. The implementation class that is derived from
POA_example must provide an implementation for this method.
The POA_example class is called a
skeleton and its method (
_op1) is invoked by the POA when a client request is received. The skeleton's internal method will marshal all the parameters for the request, invoke your
op1 method and then marshal the return parameters or exceptions into a response message. The ORB will then send the response to the client program.
In addition to the POA_example class, the IDL compiler generates a class template named
_tie_example. This template can be used if you wish to avoid deriving a class from
POA_example. Templates can be useful for providing a wrapper class for existing applications that cannot be modified to inherit from a new class. The sample below shows the template class generated by the IDL compiler for the
example class.
template <class T>
class POA_example_tie : public
POA_example {
public:
POA_example_tie (T& t): _ptr(&t),
_poa(NULL), _rel((CORBA::Boolean)0) {}
POA_example_tie (T& t,
PortableServer::POA_ptr poa): _ptr(&t),
_poa(PortableServer::_duplicate(poa)),
_rel((CORBA::Boolean)0) {}
POA_example_tie (T *p, CORBA::Boolean release= 1)
: _ptr(p),_poa(NULL), _rel(release) {}
POA_example_tie (T *p, PortableServer::POA_ptr poa,
CORBA::Boolean release =1)
: _ptr(p), _poa(PortableServer::_duplicate(poa)), _rel(release) {}
virtual
~POA_example_tie() { /* . . . */ }
T* _tied_object() { /* . . . */ }
void _tied_object(T& t) { /* . . . */ }
void _tied_object(T *p, CORBA::Boolean release=1) { /* . . . */ }
CORBA::Boolean _is_owner() { /* . . . */ }
void _is_owner(CORBA::Boolean b) { /* . . . */ }
CORBA::Long
op1(CORBA::Char _x, CORBA::Short_out _y) { /* . . . */ }
PortableServer::POA_ptr _default_POA() { /* . . . */ }
};
You may also generate a _ptie template for integrating an object database with your servers.
In addition to operations, an interface specification can also define attributes as part of the interface. By default, all attributes are read-write and the IDL compiler will generate two methods, one to set the attribute's value, and one to get the attribute's value. You can also specify
read-only attributes, for which only the reader method is generated.
class test : public virtual CORBA::Object {
...
// Methods for read-write attribute
virtual CORBA::Long count();
virtual void count(CORBA::Long __count);
// Method for read-only attribute.
virtual char * name();
...
};
IDL allows you to specify operations that have no return value, called one-way methods. These operations may only have input parameters. When a
oneway method is invoked, a request is sent to the server, but there is no confirmation from the object implementation that the request was actually received.
interface parent {
void operation1();
};
interface
child :
parent {
. . .
long operation2(in short s);
};
class parent : public virtual CORBA::Object {
...
void operation1( );
...
};
class
child : public virtual
parent {
...
CORBA::Long operation2(CORBA::Short s);
...
};