[Previous] [Contents] [Next] [IONA Technologies]


Chapter 4
The Interface Definition Language


Contents

4.1 IDL Interfaces
4.2 Oneway Operations
4.3 Context Clause
4.4 Modules
4.5 Exceptions
4.6 Inheritance
4.7 The Basic Types of IDL
4.8 Constructed Types
4.8.1 Structures
4.8.2 Enumerated Types
4.8.3 Unions
4.9 Arrays
4.10 Template Types
4.10.1 Sequences
4.10.2 Strings
4.11 Constants
4.12 Typedef Declaration
4.12.1 Forward Declaration
4.13 Scoped Names
4.14 The Preprocessor
4.15 Pseudo Types
4.15.1 The orb.idl Include File



This chapter describes the Interface Definition Language, IDL, which is used to describe the interfaces of objects in OrbixWeb. The language itself is part of the Object Management Group (OMG) CORBA specification. IDL is not a programming language because it cannot be used to implement the interfaces that are defined in IDL. An advantage of IDL is that it allows interfaces to be defined independently of the languages used to implement and use these interfaces, and therefore it makes it easy to support language interoperability.

This chapter describes the features of the IDL language. Appendix A, "IDL Reference" of the OrbixWeb Reference Guide provides some additional reference material on IDL. This includes the full syntax of the language and a list of IDL keywords.

4.1 IDL Interfaces

An IDL interface provides a description of the functionality that will be provided by an object. An interface definition provides all of the information needed to develop clients that use the interface. An interface definition typically specifies the attributes and operations belonging to that interface, as well as the parameters of each operation. Defining the interfaces between components is the most important aspect of distributed system design; therefore interfaces are the single most important feature of IDL.

Consider a simple banking application that will manage bank accounts. A user of an account object will wish to make deposits and withdrawals. An account object will also need to hold the balance of the account and perhaps the name of the account's owner. An example interface is:

The Account interface defines attributes balance and owner; these are properties of an Account object. The attribute balance may take values of type float which is one of the basic types of IDL and represents a floating point type (such as 102.31). The attribute owner is of type string and is defined to be readonly.1

Two operations, makeDeposit() and makeWithdrawal(), are provided. Each has two parameters of type float. Each parameter must specify the direction in which the parameter is passed. The possible parameter passing modes are:


     in
    
the parameter is passed from the caller (client) to the called object.

     out
    
the parameter is passed from the called object to the caller.

     inout
    
the parameter is passed in both directions.

In our example, amount is passed as an in parameter to both functions and the new balance is returned as an out parameter. The parameter passing mode must be specified for each parameter, and it is used both to improve the "self-documentation" of an interface and to help guide the code that IDL is subsequently translated to.

Line comments are introduced with the characters // as shown in the example. Comments spanning more than one line are delimited by /* and */. For example:

Multiple IDL interfaces may be defined in a single source file, but it is common to define each interface in its own file.

4.2 Oneway Operations

Normally the caller of an operation is blocked while the call is being processed by the receiver. However, an IDL operation can be defined to be oneway so that the caller is not blocked and can continue in parallel to the server. For example, we could provide a oneway operation on our Account interface to send a notice to the account:

A oneway operation must specify a void return type and cannot have out or inout parameters and it also cannot have a raises clause (see section 4.5).

Oneway operations are supported because it is sometimes important to be able to communicate with a remote object without waiting for a reply. A oneway operation differs from a normal operation (an operation not designated as oneway) that happens to have no out or inout parameters and a void return type: calls to the normal operation will block until the operation request has been carried out.

4.3 Context Clause

An IDL operation may also have a context clause associated with it. A client can maintain one or more CORBA context objects, which provide a mapping from identifiers (string names) to string values. An IDL operation can specify that it is to be provided with the client's mapping for particular identifiers–it does this by listing these identifiers following the operation declaration. For example, in the following interface definition, the operation op() specifies that it is to receive a context with two mappings: one for identifier accuracy, and one for base:

Only the identifiers (string names) are specified in the context expression. Each identifier name must begin with an alphanumeric character and can only contain alphanumerics, digits, `_' and `.'. An identifier specified in a context clause can also contain the character `*', but this character must appear at the end; it indicates that the operation is to receive the mapping for all identifiers in the client context with matching leading names. For example, an identifier "sys_*" in a context clause would match entries such as "sys_printer" and "sys_quality" in the client's context.

The advantage of a context is that a set of identifier:string mappings can be specified in one location of a large program, and a subset of these mappings can be passed to IDL operation calls spread throughout the program. The mappings can then be maintained easily in one location.

Nevertheless, contexts are one of the least important features of IDL, and extensive use should be avoided.

4.4 Modules

An interface can be defined within a module; this allows interfaces and other IDL type definitions to be grouped in logical units. This can be convenient as names defined within a module do not clash with names defined outside the module, that is, a module defines a naming scope. This allows sensible names for interfaces and other definitions to be chosen without clashing with other names.

The following example illustrates the use of a module: the interfaces related to banks are defined within a module, Finance:

The full (or scoped) name of Account is then Finance::Account.

4.5 Exceptions

An IDL operation may raise an exception indicating that an error has occurred. To illustrate exceptions, we will now extend our banking application by providing a Bank interface:

The Bank interface defines two operations:

     newAccount()
    
creates an account whose owner is the person or company whose name is passed as the parameter; the operation returns a reference to an Account object.

     deleteAccount()
    
deletes an account.

The newAccount() operation specifies, using the raises expression, that it may raise two exceptions called Reject and TooMany. The exceptions Reject and TooMany are defined within the Bank interface. The Reject exception defines a member of type string, which will be used to specify the reason that the bank rejected the request to create a new account. The TooMany exception does not define any members.

As well as user-defined exceptions, a set of standard exceptions is defined by CORBA. These correspond to standard runtime errors which may occur during the execution of a request and are listed in Appendix A, "IDL Reference" of the OrbixWeb Reference Guide.

Exceptions provide a clean way to allow an operation to raise an error to a caller. It allows an operation to specify that it may raise a set of possible error conditions. Because IDL provides a separate syntax for exceptions, this can be translated into exception handling code in programming languages that support them (including Java).

4.6 Inheritance

Our banking application also needs to consider that there are many types of bank account: checking (or current) accounts and savings accounts, for example. Both checking accounts and savings accounts share the properties of an account and respond to the same operations but these operations have different behaviour. They may also have additional properties and operations.

The relationships among these interfaces can be described in a type hierarchy as shown in Figure 4.1. The Account interface is called a base interface of CheckingAccount and SavingsAccount. Interfaces CheckingAccount and SavingsAccount are called derived interfaces of Account.


Figure 4.1: Inheritance

We can define interface CheckingAccount as:

It defines one attribute overdraftLimit, but inherits the attributes balance and owner defined in its base interface Account. Similarly, it inherits the operations makeDeposit() and makeWithdrawal() from Account, and defines a new operation orderChequebook(). An implementation of interface CheckingAccount may provide code different to an implementation of interface Account.

We can define interface SavingsAccount as:

An interface may be derived from any number of base interfaces; this is known as multiple inheritance. For example, a premium account might have the properties of both a checking account and a savings account; that is, it is an interest earning account which may also have a cheque book. Thus the inheritance hierarchy is as shown in Figure 4.2.



Figure 4.2: Multiple Inheritance

The SavingsAccount interface is defined as:

Then PremiumAccount interface may then be specified in IDL as follows:

If an interface inherits from two interfaces which contain a definition (constant, type, or exception) of the same name, then references to this interface in the derived interface will be ambiguous unless the name of the definition is qualified by its interface name, that is, unless a scoped name is given (see section 4.13). Note that it is illegal to inherit from two interfaces with the same operation or attribute name.

4.7 The Basic Types of IDL

Table 4.1 lists the basic types supported in IDL.

Type

IDL Identifier

Description

floating point type

float

double

IEEE single-precision floating point numbers.

IEEE double-precision numbers.

integer type

long

short

unsigned long

unsigned short

-231...231-1 (32bit)

-215...215-1 (16bit)

0...232-1 (32bit)

0...216-1 (16bit)

char type

char

An 8-bit quantity.

boolean type

boolean

TRUE or FALSE

octet type

octet

An 8-bit quantity that is guaranteed not to undergo any conversion during transmission.

any type

any

The any type allows the specification of values that can express an arbitrary IDL type.

Table 4.1: Basic Types

The any type allows an interface to specify that a parameter or result type may contain an arbitrary type of value to be determined at runtime.

A process that receives an any must determine what type of value it contains and then extract the value. The any type is described in Chapter 18, "Type any".

4.8 Constructed Types

As well as the basic types listed above, IDL provides three constructed types: struct, union and enum.

4.8.1 Structures

A struct data type allows related items to be packaged together. For example,

The struct PersonalDetails has two members: name of type string and age of type short. The operation getPersonalDetails() returns one of these structs.

4.8.2 Enumerated Types

An enumerated type allows the members of a set of values to be depicted by identifiers, for example:

This is more readable than defining colour as a short. The order in which the identifiers are named in the specification of an enumerated type defines the relative order of the identifiers. This order may be used by a specific programming language mapping which allows two enumerators to be compared.

4.8.3 Unions

The IDL union type provides a space saving type whereby the amount of storage required for a union is the amount necessary to store its largest element. A tag field is used to specify which member of a union instance is currently assigned a value.

The identifier following the union keyword defines a new legal type. A union type may also be named using a typedef declaration (see section 4.12).

IDL unions must be discriminated: that is, the union header must specify a tag field that determines which union member is assigned a value. In the example, the tag is called token and is of type long. Each expression that follows the case keyword must be compatible with the tag type. The type specified in parentheses after the switch keyword must be an integer, char, boolean or enum type. A default case can appear at most once in a union declaration.

4.9 Arrays

IDL provides multi-dimensional fixed-size arrays to hold lists of elements of the same type. The size of each dimension should be specified in the definition. Some example array types are:

Types bankAccounts and gridArr can be used, for example, to define parameters to an operation.

4.10 Template Types

IDL provides two template types: sequence and string, which are described in the following subsections.

4.10.1 Sequences

An IDL sequence data type allows lists of items to be passed between objects. A sequence is similar to a one-dimensional array; it has two characteristics: a maximum size, which is fixed at compile time, and a length, which is determined at runtime. A sequence differs from an array in that a sequence is not of fixed size (although a bounded sequence has a fixed maximum size). Hence, a sequence is a more flexible data type, and should be used in preference to an array except when the list of elements to be passed is always of the same size.

A sequence may be bounded or unbounded, depending on whether the maximum size is specified. For example, the type declaration:

defines a bounded sequence of size 10. The sequence vectorTen may be of any length up to the bound, 10. The type declaration:

defines an unbounded sequence.

A sequence that is used within an interface definition must be named by a typedef declaration (see section 4.12) before it can be used as the type of an attribute definition or as a parameter to an operation. For example:

A sequence that appears within a struct or union definition does not have to be named.

4.10.2 Strings

We have already used type string, which is similar to a sequence of char. A string may be bounded or unbounded depending on whether its length is specified in the declaration. A length may be specified for a string as shown in the example below:

4.11 Constants

A constant can be defined as follows:

The value of an IDL constant cannot change. Constants may be defined in an interface or module, or at global, or file level, scope (outside of any interface or module).

Constants of type long, unsigned long, short, unsigned short, char, boolean, float, double and string can be declared. Note that constants of type octet cannot be declared.

4.12 Typedef Declaration

A typedef declaration can be used to define a meaningful or a more simple name for a basic or a user-defined type. For example:

defines size as a synonym for short. Consequently the parameter declaration:

is equivalent to:

The definition:

allows a subsequent definition (for example, as a member of a structure):

4.12.1 Forward Declaration

An interface must be declared before it is referenced. A forward declaration declares the name of an interface without defining it. This allows the definition of interfaces that mutually reference each other. The syntax is the keyword interface followed by the identifier that names the interface, for example:

The interface definition must appear later in the specification.

4.13 Scoped Names

An IDL file forms a naming scope in which an identifier is defined and can be referred to. Every IDL identifier must be unique within a scope but an identifier can be reused in distinct scopes. An interface is considered to represent a distinct scope. Thus, names defined within an interface do not clash with names defined outside of that interface, for example in another interface or at file level. The following type definitions also represent distinct scopes: module, structure, union, operation and exception. The following type definitions are treated as being scoped: types, constants, enumeration values, exceptions, interfaces, attributes and operations.

A qualified or scoped name has the form <scoped_name>::<identifier>. Within a scope, a name may be used in its unqualified form.

4.14 The Preprocessor

IDL provides preprocessing directives which allow macro substitution, conditional compilation and source file inclusion. The IDL preprocessor is based on the C++ preprocessor. For example, the #include directive allows an IDL file to be included in other files.

As for a C++ include file, the following directives should be used in an IDL file that is potentially included in many other IDL files:

Other preprocessing directives available in IDL are: #define, #undef, #include, #if, #ifdef, #ifndef, #elif, #else, #endif, #defined, #error, #pragma.

4.15 Pseudo Types

CORBA defines a number of IDL pseudo interfaces, that is interfaces defined in IDL but whose implementation does not necessarily follow the normal mapping from interfaces to a target programming language. In particular, the following pseudo types are defined:

Of these, only Environment is not implemented in the OrbixWeb IDL to Java mapping.

4.15.1 The orb.idl Include File

The interface names for the CORBA pseudo types NamedValue, Principal and TypeCode are available in an IDL file only if it includes the directive:

Interface name Object (the implicit base interface of all interfaces) is available in all files.



1 An attribute declaration typically maps to two functions in the programming language, one to retrieve the value of the attribute and the other to set the value of the attribute. The readonly keyword specifies that there is only a function to retrieve the value. A readonly attribute need not be a constant: two reads of an attribute where there is an interleaving operation call can return different values.



[Roadmap] [Introduction] [GS: Applications] [GS: Applets]
[IDL] [Mapping] [Programming OrbixWeb] [Publishing Objects] [Retrieving Objects] [IIOP]
[Running Clients] [Running Servers] [Exceptions] [Inheritance] [Callbacks] [Contexts]
[API Configuration] [TypeCode] [Any] [DII] [IR] [Filters] [Smart Proxies] [Loaders] [Locators]
[Index]