# Chapter 3 C++ language mapping

Now that you are familiar with the basics, it is important to familiarise yourself with the standard IDL to C++ language mapping. The mapping is described in detail in [OMG03]. If you have not done so, you should obtain a copy of the document and use that as the programming guide to omniORB.

The specification is not an easy read. The alternative is to use one of the books on CORBA programming. For instance, Henning and Vinoski’s ‘Advanced CORBA Programming with C++’ [HV99] includes many example code fragments to illustrate how to use the C++ mapping.

## 3.1 omniORB 2 BOA compatibility

Before the Portable Object Adapter (POA) specification, many of the details of how servant objects should be implemented and registered with the system were unspecified, so server-side code was not portable between ORBs. The POA specification rectifies that. For compatibility, omniORB 4 still supports the old omniORB 2.x BOA mapping, but you should always use the POA mapping for new code. BOA code and POA code can coexist within a single program.

If you use the -WbBOA option to omniidl, it will generate skeleton code with (nearly) the same interface as the old omniORB 2 BOA mapping, as well as code to be used with the POA. Note that since the major problem with the BOA specification was that server code was not portable between ORBs, it is unlikely that omniORB’s BOA compatibility will help you much if you are moving from a different BOA-based ORB.

The BOA compatibility permits the majority of BOA code to compile without difficulty. However, there are a number of constructs which relied on omniORB 2 implementation details which no longer work.

- omniORB 2 did not use distinct types for object references and servants, and often accepted a pointer to a servant when the CORBA specification says it should only accept an object reference. Such code will not compile under omniORB 4.
- The reverse is true for BOA::obj_is_ready(). It now only works when passed a pointer to a servant object, not an object reference. The more commonly used mechanism of calling _obj_is_ready(boa) on the servant object still works as expected.
- It used to be the case that the skeleton class for interface I (_sk_I) was derived from class I. This meant that the names of any types declared in the interface were available in the scope of the skeleton class. This is no longer true. If you have an interface:
  interface I { struct S { long a,b; }; S op(); };

  then where before the implementation code might have been:

  class I_impl : public virtual _sk_I { S op(); // _sk_I is derived from I }; I::S I_impl::op() { S ret; // ... }

  it is now necessary to fully qualify all uses of S:

  class I_impl : public virtual _sk_I { I::S op(); // _sk_I is not derived from I }; I::S I_impl::op() { I::S ret; // ... }
- The proprietary omniORB 2 LifeCycle extensions are no longer supported. All of the facilities it offered can be implemented with the POA interfaces, and the omniORB::LOCATION_FORWARD exception (see section 4.8). Code which used the old interfaces will have to be rewritten.

## 3.2 omniORB 3.0 compatibility

omniORB 4 is almost completely source-code compatible with omniORB 3.0. There are two main cases where code may have to change. The first is code that uses the omniORB API, some aspects of which have changed. The omniORB configuration file also has a new format. See the next chapter for details of the new API and configuration file.

The second case of code that may have to change is code using the Dynamic Any interfaces. The standard changed quite significantly between CORBA 2.2 and CORBA 2.3; omniORB 3.0 supported the old CORBA 2.2 interfaces; omniORB 4 uses the new mapping. The changes are largely syntax changes, rather than semantic differences.

## 3.3 omniORB 4.0 compatibility

omniORB 4.3 is source-code compatible with omniORB 4.0, with four exceptions:

1. As required by the 1.1 version of the CORBA C++ mapping specification, the RefCountServantBase class has been deprecated, and the reference counting functionality moved into ServantBase. For backwards compatibility, RefCountServantBase still exists, but is now defined as an empty struct. Most code will continue to work unchanged, but code that explicitly calls RefCountServantBase::_add_ref() or _remove_ref() will no longer compile.
2. omniORB 4.0 had an option for Any extraction semantics that was compatible with omniORB 2.7, where ownership of extracted values was not maintained by the Any. That option is no longer available.
3. The members of the clientSendRequest interceptor have been changed, replacing all the separate variables with a single member of type GIOP_C. All the values previously available can be accessed through the GIOP_C instance.
4. The C++ mapping contains Any insertion operators for sequence types that are passed by pointer, which cause the Any to take ownership of the inserted sequence. In omniORB 4.0 and earlier, the sequence was immediately marshalled into the Any’s internal buffer, and the sequence was deleted. Since omniORB 4.1, the sequence pointer is stored by the Any, and the sequence is deleted later when the Any is destroyed.

   For most uses, this change is not visible to application code. However, if a sequence is constructed using an application-supplied buffer with the release flag set to false (meaning that the application continues to own the buffer), it is now important that the buffer is not deleted or modified while the Any exists, since the Any continues to refer to the buffer contents. This change means that code that worked with omniORB 4.0 may now fail with 4.1, with the Any seeing modified data or the process crashing due to accessing deleted data. To avoid this situation, use the alternative Any insertion operator using a const reference, which copies the sequence.

## 3.4 omniORB 4.1 compatibility

omniORB 4.3 is source-code compatible with omniORB 4.1 with two exceptions:

1. When omniORB 4.1 and earlier detected a timeout condition, they would throw the CORBA::TRANSIENT system exception. omniORB 4.2 and later support the CORBA::TIMEOUT system exception that was introduced with the CORBA Messaging specification. Application code that caught CORBA::TRANSIENT to handle timeouts should be changed to catch CORBA::TIMEOUT instead. Alternatively, to avoid code changes, omniORB can be configured to throw CORBA::TRANSIENT for timeouts, by setting the throwTransientOnTimeOut parameter to 1. See section 4.4.
2. sslContext has moved to the omni namespace.

## 3.5 omniORB 4.2 compatibility

omniORB 4.3 is source-code compatible with omniORB 4.2, with one exception:

1. sslContext has moved to the omni namespace.

## 3.6 Interoperability

In general, all versions of omniORB interoperate with each other, and with other CORBA implementations. There are a number of configuration options that can be set to work around interoperability with other CORBA implementations, described in section 4.6.

### 3.6.1 Exceptions in Anys

Normally, exceptions—both system exceptions and user-defined exceptions—are thrown by server operations and caught by clients. When that occurs, the GIOP protocol is completely clear that the exception is marshalled as the exception’s repository id, followed by the exception’s data members.

It is not permitted to specify an Exception as a normal operation parameter or within a constructed IDL type, but it is permitted to insert an Exception into an Any, and transmit that in an operation parameter. In that case, when the Any is marshalled, first the TypeCode is sent, and then the data value. It is somewhat ambiguous in the GIOP specification whether the value part of an Exception sent this way should contain the repository id, or not — the id is contained in the TypeCode, so sending it as part of the value too is redundant.

Versions of omniORB for C++ prior to 4.3 did not send the Exception repository id in the value part of an Any. All versions of omniORBpy do send it, as do some other CORBA implementations. For interoperability, omniORB 4.3 has changed to send the repository id. This means that it is compatible with omniORBpy and other ORBs, but that it is incompatible with previous versions of omniORB for C++. The exceptionIdInAny configuration parameter can be set to false to revert to the prior behaviour if interoperability with earlier omniORB versions is required.