OMG® IDL: Details
How does OMG IDL enable distribution?
Encapsulation is the principle of object-orientation that enables seamless distribution. By encapsulating the internal structure and mechanism of our objects inside a boundary that the client is not allowed to penetrate, we gain not only flexibility but also a simplicity of architecture that could not be achieved any other way. We use OMG IDL to define the interface that sits on the outside of the boundary, allowing the only communication that the object conducts with the outside world.
For distribution to work in this architecture, we need to define interfaces that both client and server object understand and can use easily, regardless of their platform, operating system, programming language, network connection, or other characteristics. (Keep in mind that we will use this same interface definition language for embedded systems and unreliable wireless links, as well as for clients and servers connected by robust copper and fiber.) An interface definition must specify the operation to be performed, and all of the input and output parameters with their types, allowing client and server to encode and decode values for their travel over the network. The language should also enforce the architecture - for CORBA, object orientation - that we've chosen as the basis for our distributed system. And finally, since it's always possible for something to go wrong when we make an invocation, the language should support robust exception handling.
Or, you can download it from OMG's website, here where it's Chapter 3.
Tell me about IDL's type system
IDL Types work at two levels:
First, every CORBA object has a type name, which is the same as the interface name you assign in its IDL declaration. The operations that it can perform, and the variables (and their types!) that it understands, are all part of its type. Every time you define a new kind of CORBA object as you write OMG IDL (by declaring a new interface), you create a new CORBA type.
Second (and as we had to mention already), IDL variables are typed but not in the same way as CORBA objects. You don't create types for variables; instead you have to choose from the official list of types allowed by the IDL specification. It's a full list; base types include three different precisions of integers and floating-point numbers plus fixed-point; standard and wide characters and strings; boolean; valuetype (we'll write a separate page about the valuetype soon); and octet for when you absolutely have to send a binary value that only your application understands. Constructed types include the structure ("struct"), union, and enum. You can declare either fixed or variable length structs, arrays, strings, and wstrings. There's an any type that can be assume any legal IDL type at runtime. The CORBA object reference is also an IDL type - you can (and will!) pass CORBA object references around your system as parameters to invocations.
If you implement in an object-oriented language (using the language mappings that we'll talk about next), IDL and the mechanisms of your language work together to enforce the type system. Attempts to invoke an operation on an object type that doesn't support it will produce errors at compile time instead of run time, speeding development and enhancing code correctness.
OMG IDL is strongly typed: Typing is enforced at compile time (if you use an object-oriented language for your implementation). The any type provides flexibility.
How are these type definitions scoped?
IDL defines scopes that delimit where your type definitions may be used. If you use namespaces in C++, you're already familiar with the concept.
There's a global scope, which encompasses your entire compilation unit. (If you include multiple files in your compilation, the global scope spans all of them. No scope corresponds to a file.) Next, you can declare a module delimited by curly braces { }; types declared at module level are valid anywhere within it. interface defines the next level and gives you another opportunity to declare types, and each operation does the same. valuetypes, structs, unions, and exceptions also define scopes.
You can import a definition from the scope that defines it to any other scope with the importation operator, :: (double colon).
What does IDL look like?
IDL interface definitions are elegant and (usually!) easy to write and understand. Here's an interface from the programming example in the book CORBA® 3 Fundamentals and Programming:
interface salestax {
float calculate_tax ( in float
taxable_amount );
}
This is the interface to an object that calculates sales tax in a store's computing system. The object's type is salestax, and it can perform one operation: calculate_tax. The object takes one input parameter, taxable_amount, which is a float. The return value, which does not need a name, is also a float.
This very simple example doesn't show any of IDL's more sophisticated features and capabilities. Experienced CORBA programmers use structs, sequences, attributes, valuetypes, and other IDL types and constructs to create very flexible data structures for their interfaces. In this brief tutorial, this simple one-line example is about as far as we can go.
Interfaces for OMG's standard CORBAservices, CORBAfacilities, and Domain Facilities are all specified in OMG IDL. Under the MDA, these services and facilities will also be specified in other middleware platforms.
How does this work in My programming language?
In order to integrate the heterogeneous computing environment that we've built up over the years, CORBA® needs to work in just about every programming language. IDL is not a programming language - it's great for defining interfaces, but it doesn't have the constructs you'd need to write a program.
To do this, OMG has defined mappings from IDL to just about every major programming language: C, C++, C++11, Java, Smalltalk, COBOL, Ada, Lisp, PL/1, Python, Ruby, and IDLscript have standard mappings. Implementations of mappings to other languages are available.
A mapping assigns a language variable type to each IDL variable type, and a translation from IDL's operation format to the language's invocation of a member function or other operation invocation format. Mappings also specify memory usage conventions for client and server sides, and conventions that allow CORBA's infrastructure to perform services for the object implementation: A mapping to an OO language might, for example, assign names to the base classes for the implementation and specify how the implementation classes should derive from IDL-generated classes.
Language mappings are very precise: When you apply an OMG language mapping to an IDL file, you always get the same language constructs out. To our distributed programming environment, this provides portability in addition to predictability.
What does an IDL Compiler do?
IDL Compilers implement language mappings in software. Every ORB comes with one or more IDL compilers, one for each language that it supports. After you've written your IDL interface file, you run it through an IDL compiler that came with your ORB. Because the mappings are standard, and compilers implement this standard, every vendor's IDL compiler will produce language code with the same mappings, allowing your same client and server code to port from vendor to vendor without change (as long as you resist vendor extensions, of course).
After checking your IDL for errors, the compiler will produce at least two files: one for the client stub; the other for the object skeleton. For more on what these are and how they work, go to the main CORBA tutorial FAQ and read on.