The IDL compiler

# Chapter 5 The IDL compiler

omniORB’s IDL compiler is called omniidl. It consists of a generic front-end parser written in C++, and a number of back-ends written in Python. omniidl is very strict about IDL validity, so you may find that it reports errors in IDL which compiles fine with other IDL compilers.

The general form of an omniidl command line is:

> omniidl [options] -b<back-end> [back-end options] <file>

## 5.1 Common options

The following options are common to all back-ends:

-bback-end | Run the specified back-end. For the C++ ORB, use -bcxx.
-Dname[=value] | Define name for the preprocessor.
-Uname | Undefine name for the preprocessor.
-Idir | Include dir in the preprocessor search path.
-E | Only run the preprocessor, sending its output to stdout.
-Ycmd | Use cmd as the preprocessor, rather than the normal C preprocessor.
-N | Do not run the preprocessor.
-T | Use a temporary file, not a pipe, for preprocessor output.
-Wparg[,arg…] | Send arguments to the preprocessor.
-Wbarg[,arg…] | Send arguments to the back-end.
-nf | Do not warn about unresolved forward declarations.
-k | Keep comments after declarations, to be used by some back-ends.
-K | Keep comments before declarations, to be used by some back-ends.
-Cdir | Change directory to dir before writing output files.
-d | Dump the parsed IDL then exit, without running a back-end.
-pdir | Use dir as a path to find omniidl back-ends.
-V | Print version information then exit.
-u | Print usage information.
-v | Verbose: trace compilation stages.

Most of these options are self explanatory, but some are not so obvious.

### 5.1.1 Preprocessor interactions

IDL is processed by the C preprocessor before omniidl parses it. omniidl always uses the GNU C preprocessor (which it builds with the name omnicpp). The -D, -U, and -I options are just sent to the preprocessor. Note that the current directory is not on the include search path by default—use ‘-I.’ for that. The -Y option can be used to specify a different preprocessor to omnicpp. Beware that line directives inserted by other preprocessors are likely to confuse omniidl.

#### 5.1.1.1 Ancient history: Windows 9x

The output from the C preprocessor is normally fed to the omniidl parser through a pipe. On some Windows 98 machines (but not all!) the pipe does not work, and the preprocessor output is echoed to the screen. When this happens, the omniidl parser sees an empty file, and produces useless stub files with strange long names. To avoid the problem, use the ‘-T’ option to create a temporary file between the two stages.

### 5.1.2 Forward-declared interfaces

If you have an IDL file like:

interface I; interface J { attribute I the_I; };

then omniidl will normally issue a warning:

      test.idl:1: Warning: Forward declared interface `I' was never
      fully defined

It is illegal to declare such IDL in isolation, but it is valid to define interface I in a separate file. If you have a lot of IDL with this sort of construct, you will drown under the warning messages. Use the -nf option to suppress them.

### 5.1.3 Comments

By default, omniidl discards comments in the input IDL. However, with the -k and -K options, it preserves the comments for use by the back-ends. The C++ back-end ignores this information, but it is relatively easy to write new back-ends which do make use of comments.

The two different options relate to how comments are attached to declarations within the IDL. Given IDL like:

interface I { void op1(); // A comment void op2(); };

the -k flag will attach the comment to op1(); the -K flag will attach it to op2().

## 5.2 C++ back-end options

When you specify the C++ back-end (with -bcxx), the following -Wb options are available. Note that the -Wb options must be specified after the -bcxx option, so omniidl knows which back-end to give the arguments to.

-Wbh=suffix | Use suffix for generated header files. Default ‘.hh’.
-Wbs=suffix | Use suffix for generated stub files. Default ‘SK.cc.’
-Wbd=suffix | Use suffix for generated dynamic files. Default ‘DynSK.cc.’
-Wba | Generate stubs for TypeCode and Any.
-Wbtp | Generate ‘tie’ implementation skeletons.
-Wbtf | Generate flattened ‘tie’ implementation skeletons.
-Wbami | Generate AMI types and operations.
-Wbexample | Generate example implementation code.
-Wbinline | Output stubs for #included IDL files in line with the main file.
-Wbuse-quotes | Use quotes in ‘#include’ directives (e.g. "foo" rather than <foo>.)
-Wbkeep-inc-path | Preserve IDL ‘#include’ paths in generated ‘#include’ directives.
-Wbvirtual-objref | Use virtual functions for object reference operations.
-Wbimpl-mapping | Use the ‘implementation’ mapping for object reference methods.
-Wbsplice-modules | Splice together multiply-opened modules into one.
-WbBOA | Generate BOA compatible skeletons.
-Wbold | Generate old CORBA 2.1 signatures for skeletons.
-Wbold-prefix | Map C++ reserved words with prefix ‘_’ rather than ‘_cxx_’.
-WbF | Generate code fragments (only for use during omniORB build).

### 5.2.1 Optional code generation options

By default, omniidl generates the minimum code required to provide all the IDL-defined types and interfaces, which is sufficient for the majority of applications. Additional code can also be generated, for various purposes:

#### 5.2.1.1 Any and TypeCode

To generate TypeCodes and Any insertion operators, give the -Wba option. See chapter 10 for details.

By default, omniidl separates the normal stub and skeleton file (the SK.cc file) from these ‘dynamic’ stubs (the DynSK.cc file), so applications that do not need support for Any and TypeCode for a particular IDL file do not waste space with unnecessary definitions. It is possible to output both the normal stubs and the dynamic stubs to a single file, by simply specifying the same extension for both files. This command places both the normal stubs and the dynamic stubs in aSK.cc:

> omniidl -bcxx -Wba -Wbd=SK.cc a.idl

#### 5.2.1.2 Tie templates

As described in section 2.11, tie templates can be used to provide servant implementations, instead of using inheritance from the normal skeleton classes. To generate tie templates, give the -Wbtp option to omniidl.

When using a pre-namespace C++ compiler, IDL modules are mapped to C++ classes, which causes a problem with tie templates. The C++ mapping says that for the interface M::I, the C++ tie template class should be named POA_M::I_tie. However, since template classes cannot be declared inside other classes, this naming scheme cannot be used if POA_M is a class.

The C++ mapping has an alternative option of ‘flattened’ tie class names, in which the template class is declared at global scope with the name POA_M_I_tie. i.e. all occurrences of ‘::’ are replaced by ‘_’. Generate the flattened ties using the -Wbtf command line argument.

#### 5.2.1.3 Asynchronous Method Invocation

Generate asynchronous invocation operations and the various types required by AMI by specifying -Wbami. See chapter 12 for details.

#### 5.2.1.4 Example implementations

If you use the -Wbexample flag, omniidl will generate an example implementation file as well as the stubs and skeletons. For IDL file foo.idl, the example code is written to foo_i.cc. The example file contains class and method declarations for the operations of all interfaces in the IDL file, along with a main() function which creates an instance of each object. You still have to fill in the operation implementations, of course.

### 5.2.2 Include file options

IDL files regularly #include other files. By default, if file a.idl says #include <b/c.idl> then the generated header a.hh has an include of the form #include <c.idl>, and aSK.cc and aDynSK.cc contain only code corresponding to the declarations in a.idl.

If the -Wbinline option is provided, all the #included declarations are generated in a.hh, aSK.cc and aDynSK.cc, meaning the application code should only use that single set of files.

If -Wbuse-quotes is specified, then the directive in a.hh uses quotes rather than angle brackets: #include "c.idl".

Normally any path details contained in the IDL #include directive are removed, leaving just the base name. If -Wbkeep-inc-path is specified, the directive in a.hh is #include <b/c.idl>.

### 5.2.3 Object reference operations

Some of the C++ mapping’s parameter passing rules are problematic in terms of memory management. For example, if an IDL operation has a parameter of type inout string, the standard mapping has a C++ parameter of type char*&. If application code passes a String_var for the parameter, some C++ compilers choose the wrong conversion operator and cause a violation of the memory management rules1.

To avoid this, omniORB uses some helper classes as the parameter types in object reference operations, meaning that the correct memory management rules are always followed. Normally, that is invisible to application code, but occasionally it becomes problematic. One example is that if a local interface is derived from a normal unconstrained interface, the C++ mapping of the local interface derives from the object reference class, and so the base object reference class must use the standard mapping rather than omniORB’s usual enhanced mapping. To choose the standard ‘implementation mapping’, give the -Wbimpl-mapping option to omniidl.

Similarly, omniidl usually uses non-virtual methods in its object reference classes, since there is no usual need to override them. The local interface situation also requires method overrides, so omniidl must be instructed to generate object references as virtual. Use -Wbvirtual-objref to achieve this.

More details about the local interface mapping can be found in section 11.8.

### 5.2.4 Module splicing

On ancient C++ compilers without namespace support, IDL modules map to C++ classes, and so cannot be reopened. For some IDL, it is possible to ‘splice’ reopened modules on to the first occurrence of the module, so all module definitions are in a single class. It is possible in this sort of situation:

module M1 { interface I {}; }; module M2 { interface J { attribute M1::I ok; }; }; module M1 { interface K { attribute I still_ok; }; };

but not if there are cross-module dependencies:

module M1 { interface I {}; }; module M2 { interface J { attribute M1::I ok; }; }; module M1 { interface K { attribute M2::J oh_dear; }; };

In both of these cases, the -Wbsplice-modules option causes omniidl to put all of the definitions for module M1 into a single C++ class. For the first case, this will work fine. For the second case, class M1::K will contain a reference to M2::J, which has not yet been defined; the C++ compiler will complain.

## 5.3 Examples

Generate the C++ headers and stubs for a file a.idl:

> omniidl -bcxx a.idl

Generate with Any support:

> omniidl -bcxx -Wba a.idl

As above, but also generate Python stubs (assuming omniORBpy is installed):

> omniidl -bcxx -Wba -bpython a.idl

Just check the IDL files for validity, generating no output:

> omniidl a.idl b.idl

1
  For this reason, the _var types define an inout() method that ensures use of the correct conversion and thus avoids this kind of trouble.