The CORBA specification provides for a type that can hold the value of any OMG IDL type. This type is known as type Any. The OMG also specifies a pseudo-object, TypeCode, that can encode a description of any type specifiable in OMG IDL.
In this chapter, an example demonstrating the use of type Any is presented. This is followed by sections describing the behaviour of type Any and TypeCode in omniORB. For further information on type Any, refer to the C++ Mapping specification., and for more information on TypeCode, refer to the Interface Repository chapter in the CORBA core section of the CORBA specification.
Before going through this example, you should make sure that you have read and understood the examples in chapter 2. The source code for this example is included in the omniORB distribution, in the directory src/examples/anyExample. A listing of the source code is provided at the end of this chapter.
Type Any allows one to delay the decision on the type used in an operation until run-time. To use type any in IDL, use the keyword any, as in the following example:
The operation testOp()() in this example can now take any value expressible in OMG IDL as an argument, and can also return any type expressible in OMG IDL.
Type Any is mapped into C++ as the type CORBA::Any. When passed as an argument or as a result of an operation, the following rules apply:
So, the above IDL would map to the following C++:
The question now arises as to how values are inserted into and removed from an Any. This is achieved using two overloaded operators: <<= and >>=.
To insert a value into an Any, the <<= operator is used, as in this example:
Note that the overloaded <<= operator has a return type of void.
To extract a value, the >>= operator is used, as in this example (where the Any contains a long):
The overloaded >>= operator returns a CORBA::Boolean. If an attempt is made to extract a value from an Any when it contains a different type of value (e.g. an attempt to extract a long from an Any containing a double), the overloaded >>= operator will return False; otherwise it will return True. Thus, a common tactic to extract values from an Any is as follows:
It is also possible to insert and extract constructed types and object references from an Any. omniidl will generate insertion and extraction operators for the constructed type. Note that it is necessary to specify the -WBa command-line flag when running omniidl in order to generate these operators. The following example illustrates the use of constructed types with type Any:
Upon compiling the above IDL with omniidl -bcxx -Wba, the following overloaded operators are generated:
void operator<<=(CORBA::Any&, const testStruct&)
void operator<<=(CORBA::Any&, testStruct*)
CORBA::Boolean operator>>=(const CORBA::Any&,
Operators of this form are generated for all constructed types, and for interfaces.
The first operator, (1), copies the constructed type, and inserts it into the Any. The second operator, (2), inserts the constructed type into the Any, and then manages it. Note that if the second operator is used, the Any consumes the constructed type, and the caller should not use the pointer to access the data after insertion. The following is an example of how to insert a value into an Any using operator (1):
The third operator, (3), is used to extract the constructed type from the Any, and can be used as follows:
As with basic types, if an attempt is made to extract a type from an Any that does not contain a value of that type, the extraction operator returns False. If the Any does contain that type, the extraction operator returns True. If the extraction is successful, the caller’s pointer will point to memory managed by the Any. The caller must not delete or otherwise change this storage, and should not use this storage after the contents of the Any are replaced (either by insertion or assignment), or after the Any has been destroyed. In particular, management of the pointer should not be assigned to a _var type.
If the extraction fails, the caller’s pointer will be set to point to null.
Note that there are special rules for inserting and extracting arrays (using the _forany types), and for inserting and extracting bounded strings, booleans, chars, and octets. Please refer to the C++ Mapping specification for further information.
This section contains some notes on the use and behaviour of type Any in omniORB.
To generate type Any insertion and extraction operators for constructed types and interfaces, the -Wba command line flag should be specified when running omniidl.
When an attempt is made to extract a type from an Any, the TypeCode of the type is checked for equivalence with the TypeCode of the type stored by the Any. The equivalent() test in the TypeCode interface is used for this purpose.
If an attempt is made to extract the type Test1 defined in IDL 1 from an Any containing the Test1 defined in IDL 2, this will succeed (and vice-versa), as the two types differ only by an alias.
When a type is inserted into an Any, the Any stores both the value of the type and the TypeCode for that type. However, in some cases, a top-level alias can be lost due to the details of the C++ mapping. For example, consider these IDL definitions:
omniidl generates distinct types for seqDouble1 and seqDouble2, and therefore each has its own set of C++ operators for Any insertion and extraction. That means inserting a seqDouble1 into an Any sets the Any’s TypeCode to include the alias ‘seqDouble1’, and inserting a seqDouble2 sets the TypeCode to the alias ‘seqDouble2’.
However, in the C++ mapping, seqDouble3 is required to be just a C++ typedef to seqDouble2, so the C++ compiler uses the Any insertion operator for seqDouble2. Therefore, inserting a seqDouble3 sets the Any’s TypeCode to the seqDouble2 alias. If this is not desirable, you can use the member function ‘void type(TypeCode_ptr)’ of the Any interface to explicitly set the TypeCode to the correct one.
Some ORBs (such as old versions of Orbix) will not accept TypeCodes containing tk_alias TypeCodes. When using type Any while interoperating with these ORBs, it is necessary to remove tk_alias TypeCodes from throughout the TypeCode representing a constructed type.
To remove all tk_alias TypeCodes from TypeCodes transmitted in Anys, supply the -ORBtcAliasExpand 1 command-line flag when running an omniORB executable. There will be some (small) performance penalty when transmitting Any values.
Note that the _tc_ TypeCodes generated for all constructed types will contain the complete TypeCode for the type (including any tk_alias TypeCodes), regardless of whether the -ORBtcAliasExpand flag is set to 1 or not. It is only when Anys are transmitted that the aliases are stripped.
omniORB supports recursive TypeCodes. This means that types such as the following can be inserted or extracted from an Any:
Inserting and extracting simultaneously from the same Any (in 2 different threads) results in undefined behaviour.
In versions of omniORB before 4.0, extracting simultaneously from the same Any (in 2 or more different threads) also led to undefined behaviour. That is no longer the case—Any extraction is now thread safe.
This section contains some notes on the use and behaviour of TypeCode in omniORB
When using TypeCodes in IDL, note that they are defined in the CORBA scope. Therefore, CORBA::TypeCode should be used. Example:
The CORBA specification says that IDL using CORBA::TypeCode must include the file orb.idl. That is not required in omniORB, but a suitable orb.idl is available.
To generate a TypeCode for constructed types, specify the -Wba command-line flag when running omniidl. This will generate a _tc_ TypeCode describing the type, at the same scope as the type. Example:
A TypeCode, _tc_Test6, will be generated to describe the struct Test6. The operations defined in the TypeCode interface can be used to query the TypeCode about the type it represents.