Sophie

Sophie

distrib > Mandriva > 8.2 > i586 > by-pkgid > b53adf8a0c2b67740bddc191aeb39a8a > files > 20

libomniorb3-doc-3.04-4mdk.i586.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.05">
<TITLE>
 Type Any and TypeCode
</TITLE>
</HEAD>
<BODY >
<A HREF="omniORB008.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="omniORB010.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H1>Chapter&nbsp;9&nbsp;&nbsp; Type Any and TypeCode</H1>
<A NAME="ch_any"></A>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.<BR>
<BR>
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 section of the CORBA 2.3
specification&nbsp;[<A HREF="omniORB014.html#corba23-spec"><CITE>OMG99</CITE></A>], and for more information on
TypeCode, refer to the Interface Repository chapter in the CORBA core
section of the CORBA 2.3 specification.<BR>
<BR>
<HR SIZE=2><DL COMPACT=compact>
<DT><DD>
<DIV ALIGN=center><B>Warning</B></DIV><BR>
Since 2.8.0, omniORB has been updated to CORBA 2.3. In order to comply
with the 2.3 specification, it is necessary to change the semantics of
<EM>the extraction of string, object reference and typecode from an
Any</EM>. The memory of the extracted values of these types now belongs to
the Any value. The storage is freed when the Any value is deallocated.
Previously the extracted value was a copy and the application was
responsible for releasing the storage. It is not possible to detect
the old usage at compile time. In particular, unmodified code that
uses the affected Any extraction operators will most certainly cause
runtime errors to occur. To smooth the transition from the old usage
to the new, an ORB configuration variable
<TT>omniORB::omniORB_27_CompatibleAnyExtraction</TT> can be set to
revert the any extraction operators to the old semantics.</DL><HR SIZE=2><BR>
<BR>
<A NAME="toc47"></A>
<H2>9.1&nbsp;&nbsp; Example using type Any</H2>Before going through this example, you should make sure that you have
read and understood the examples in chapter&nbsp;<A HREF="omniORB002.html#ch_basic">2</A>. The
source code for this example is included in the omniORB distribution,
in the directory <TT>src/examples/anyExample</TT>. A listing of the
source code is provided at the end of this chapter.<BR>
<BR>

<H3>9.1.1&nbsp;&nbsp; Type Any in IDL</H3>
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
<TT>any</TT>, as in the following example:<BR>
<BR>
<PRE>
// IDL

interface anyExample {
  any testOp(in any mesg);
};
</PRE>The operation <TT>testOp()()</TT> 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.<BR>
<BR>
Type Any is mapped into C++ as the type <TT>CORBA::Any</TT>. When passed
as an argument or as a result of an operation, the following rules
apply:<BR>
<BR>
<BR>
<BR>
<TABLE CELLSPACING=2 CELLPADDING=0>
<TR><TD ALIGN=left NOWRAP><B>In </B></TD>
<TD ALIGN=left NOWRAP><B>InOut </B></TD>
<TD ALIGN=left NOWRAP><B>Out </B></TD>
<TD ALIGN=left NOWRAP><B>Return </B></TD>
</TR>
<TR><TD BGCOLOR=black COLSPAN=4><TABLE BORDER=0 WIDTH="100%" CELLSPACING=0 CELLPADING=1><TR><TD></TD></TR></TABLE></TD>
</TR>
<TR><TD ALIGN=left NOWRAP><TT>const CORBA::Any&amp; </TT></TD>
<TD ALIGN=left NOWRAP><TT>CORBA::Any&amp; </TT></TD>
<TD ALIGN=left NOWRAP><TT>CORBA::Any*&amp; </TT></TD>
<TD ALIGN=left NOWRAP><TT>CORBA::Any* </TT></TD>
</TR></TABLE>
<BR>
<BR>
<BR>
So, the above IDL would map to the following C++:<BR>
<BR>
<PRE>
// C++

class anyExample_i : public virtual _sk_anyExample {
public:
  anyExample_i() { }
  virtual ~anyExample_i() { }
  virtual CORBA::Any* testOp(const CORBA::Any&amp; a);
};
</PRE>
<H3>9.1.2&nbsp;&nbsp; Inserting and Extracting Basic Types from an Any</H3>The question now arises as to how values are inserted into and removed
from an Any. This is achieved using two overloaded operators:
<TT>&lt;&lt;=</TT> and <TT>&gt;&gt;=</TT>.<BR>
<BR>
To insert a value into an Any, the <TT>&lt;&lt;=</TT> operator is used, as
in this example:<BR>
<BR>
<PRE>
// C++
CORBA::Any an_any;
CORBA::Long l = 100;
an_any &lt;&lt;= l;
</PRE>Note that the overloaded <TT>&lt;&lt;=</TT> operator has a return type of
<TT>void</TT>.<BR>
<BR>
To extract a value, the <TT>&gt;&gt;=</TT> operator is used, as in this
example (where the Any contains a long):<BR>
<BR>
<PRE>
// C++
CORBA::Long l;
an_any &gt;&gt;= l;

cout &lt;&lt; "This is a long: " &lt;&lt; l &lt;&lt; endl;
</PRE>The overloaded <TT>&gt;&gt;=</TT> operator returns a <TT>CORBA::Boolean</TT>.
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 <TT>&gt;&gt;=</TT> operator will
return False; otherwise it will return True. Thus, a common tactic to
extract values from an Any is as follows:<BR>
<BR>
<PRE>
// C++
CORBA::Long l;
CORBA::Double d;
const char* str;     // From CORBA 2.3 onwards, uses const char*
                     // instead of char*. 

if (an_any &gt;&gt;= l) {
    cout &lt;&lt; "Long: " &lt;&lt; l &lt;&lt; endl;
}
else if (an_any &gt;&gt;= d) {
    cout &lt;&lt; "Double: " &lt;&lt; d &lt;&lt; endl;
}
else if (an_any &gt;&gt;= str) {
    cout &lt;&lt; "String: " &lt;&lt; str &lt;&lt; endl;
    // Since 2.8.0 the storage of the extracted string is still
    // owned by the any.
    // In pre-omniORB 2.8.0 releases, the string returned is a copy.
}
else {
    cout &lt;&lt; "Unknown value." &lt;&lt; endl;
}
</PRE>
<H3>9.1.3&nbsp;&nbsp; Inserting and Extracting Constructed Types from an Any</H3>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 <TT>-WBa</TT> command-line flag when running omniidl in
order to generate these operators. The following example illustrates
the use of constructed types with type Any:<BR>
<BR>
<PRE>
// IDL
struct testStruct {
  long l;
  short s;
};

interface anyExample {
  any testOp(in any mesg);
};
</PRE>Upon compiling the above IDL with <TT>omniidl -bcxx -Wba</TT>, the
following overloaded operators are generated:<BR>
<BR>
<OL type=1>
<LI>
 <CODE>void operator&lt;&lt;=(CORBA::Any&amp;, const testStruct&amp;)</CODE>

<LI> <CODE>void operator&lt;&lt;=(CORBA::Any&amp;, testStruct*)</CODE>

<LI> <CODE>CORBA::Boolean operator&gt;&gt;=(const CORBA::Any&amp;,</CODE><BR><CODE>const testStruct*&amp;)</CODE>
</OL>Operators of this form are generated for all constructed types, and
for interfaces.<BR>
<BR>
The first operator, <EM>(1)</EM>, copies the constructed type, and
inserts it into the Any. The second operator, <EM>(2)</EM>, 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 <EM>(1)</EM>:<BR>
<BR>
<PRE>
// C++
CORBA::Any an_any;

testStruct t;
t.l = 456;
t.s = 8;

an_any &lt;&lt;= t;
</PRE>The third operator, <EM>(3)</EM>, is used to extract the constructed
type from the Any, and can be used as follows:<BR>
<BR>
<PRE>
const testStruct* tp;   // From CORBA 2.3 onwards, use 
                        // const testStruct* instead of testStruct*

if (an_any &gt;&gt;= tp) {
    cout &lt;&lt; "testStruct: l: " &lt;&lt; tp-&gt;l &lt;&lt; endl;
    cout &lt;&lt; "            s: " &lt;&lt; tp-&gt;s &lt;&lt; endl;
}
else {
    cout &lt;&lt; "Unknown value contained in Any." &lt;&lt; endl;
}
</PRE>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
<TT>_var</TT> type.<BR>
<BR>
If the extraction fails, the caller's pointer will be set to point to
null.<BR>
<BR>
Note that there are special rules for inserting and extracting arrays
(using the <TT>_forany</TT> types), and for inserting and extracting
bounded strings, booleans, chars, and octets. Please refer to the C++
Mapping chapter of the CORBA 2.3 specification&nbsp;[<A HREF="omniORB014.html#corba23-spec"><CITE>OMG99</CITE></A>] for
further information.<BR>
<BR>
<HR SIZE=2><DL COMPACT=compact>
<DT><DD>
<DIV ALIGN=center><B>Warning</B></DIV><BR>
In pre-omniORB 2.8.0 releases, it was unclear in the CORBA
specification whether or not object references should be managed by an
Any. The omniORB implementation leaves management of an extracted
object reference to the caller. Therefore, the programmer should
release object references and TypeCodes that have been extracted from
an Any. The same also applies to string extraction. CORBA 2.3 has
clarified this issue and decreed that the management of an extracted
object reference still belongs to the Any! Since 2.8.0, the omniORB
implementation conforms to the CORBA 2.3 specification. For backward
compatibility, the runtime variable
<TT>omniORB::omniORB_27_CompatibleAnyExtraction</TT> can be set to 1
to get back the old behaviour. Notice that this should be used as a
transitional measure and in the long run, applications should be
written to use the new behaviour.</DL><HR SIZE=2><BR>
<BR>
<A NAME="toc48"></A>
<H2>9.2&nbsp;&nbsp; Type Any in omniORB</H2>
<A NAME="anyOmniORB"></A>This section contains some notes on the use and behaviour of type Any
in omniORB.<BR>
<BR>

<H5>Generating Insertion and Extraction Operators.</H5>
To generate type Any insertion and extraction operators for
constructed types and interfaces, the <TT>-Wba</TT> command line flag
should be specified when running omniidl.<BR>
<BR>

<H5>TypeCode comparison when extracting from an Any.</H5>
When an attempt is made to extract a type from an Any, the TypeCode of
the type is checked for <EM>equivalence</EM> with the TypeCode of the
type stored by the Any. The <TT>equivalent()</TT> test in the TypeCode
interface is used for this purpose<A NAME="text20" HREF="#note20"><SUP><FONT SIZE=2>1</FONT></SUP></A>.<BR>
<BR>
Examples:<BR>
<BR>
<PRE>
// IDL 1
typedef double Double1;

struct Test1 {
  Double1 a;
};
</PRE><PRE>
// IDL 2
typedef double Double2;

struct Test1 {
  Double2 a;
};
</PRE>If an attempt is made to extract the type <TT>Test1</TT> defined in IDL
1 from an Any containing the <TT>Test1</TT> defined in IDL 2, this will
succeed (and vice-versa), as the two types differ only by an alias.<BR>
<BR>

<H5>Top-level aliases.</H5>
When a type is inserted into an Any, the Any stores both the value of
the type and the TypeCode for that type. The treatment of top-level
aliases from omniORB 2.8.0 onwards is different from pre-omniORB 2.8.0
releases.<BR>
<BR>
In pre-omniORB 2.8.0 releases, if there are any top-level
<TT>tk_alias</TT> TypeCodes in the TypeCode, they will be removed from
the TypeCode stored in the Any. Note that this does not affect the
<TT>_tc_</TT> TypeCode generated to represent the type (see section on
TypeCode, below). This behaviour is necessary, as two types that
differ only by a top-level alias can use the same insertion and
extraction operators. If the <TT>tk_alias</TT> is not removed, one of
the types could be transmitted with an incorrect <TT>tk_alias</TT>
TypeCode. Example:<BR>
<BR>
<PRE>
// IDL 3
typedef sequence&lt;double&gt; seqDouble1;
typedef sequence&lt;double&gt; seqDouble2;
typedef seqDouble2       seqDouble3;
</PRE>If either <TT>seqDouble1</TT> or <TT>seqDouble2</TT> is inserted into an
Any, the TypeCode stored in the Any will be for a
<TT>sequence&lt;double&gt;</TT>, and not for an alias to a
<TT>sequence&lt;double&gt;</TT>.<BR>
<BR>
From omniORB 2.8.0 onwards, there are two changes. Firstly, in the
example, <TT>seqDouble1</TT> and <TT>seqDouble2</TT> are now distinct
types and therefore each has its own set of C++ operators for Any
insertion and extraction. Secondly, the top level aliases are not
removed. For example, if <TT>seqDouble3</TT> is inserted into an Any,
the insertion operator for <TT>seqDouble2</TT> is invoked (because
<TT>seqDouble3</TT> is just a C++ typedef of
<TT>seqDouble2</TT>). Therefore, the TypeCode in the Any would be that
of seqDouble2. If this is not desirable, one can use the new member
function `<TT>void type(TypeCode_ptr)</TT>' of the Any interface to
explicitly set the TypeCode to the correct one.<BR>
<BR>

<H5>Removing aliases from TypeCodes.</H5>
Some ORBs (such as Orbix) will not accept TypeCodes containing
<TT>tk_alias</TT> TypeCodes. When using type Any while interoperating
with these ORBs, it is necessary to remove <TT>tk_alias</TT> TypeCodes
from throughout the TypeCode representing a constructed type.<BR>
<BR>
To remove all <TT>tk_alias</TT> TypeCodes from TypeCodes stored in
Anys, supply the <TT>-ORBtcAliasExpand 1</TT> command-line flag when
running an omniORB executable. There will be some (small) performance
penalty when inserting values into an Any.<BR>
<BR>
Note that the <TT>_tc_</TT> TypeCodes generated for all constructed
types will contain the complete TypeCode for the type (including any
<TT>tk_alias</TT> TypeCodes), regardless of whether the
<TT>-ORBtcAliasExpand</TT> flag is set to 1 or not.<BR>
<BR>

<H5>Recursive TypeCodes.</H5>
omniORB (as of version 2.7) supports recursive TypeCodes. This means
that types such as the following can be inserted or extracted from an
Any:<BR>
<BR>
<PRE>
// IDL 4
struct Test4 {
  sequence&lt;Test4&gt; a;
};
</PRE>
<H5>Type-unsafe construction and insertion.</H5>
If using the type-unsafe Any constructor, or the
<TT>CORBA::Any::replace()</TT> member function, ensure that the value
returned by the <TT>CORBA::Any::value()</TT> member function and the
TypeCode returned by the <TT>CORBA::Any::type()</TT> member function are
used as arguments to the constructor or function. Using other values
or TypeCodes may result in a mismatch, and is undefined behaviour.<BR>
<BR>
Note that a non-CORBA 2 function,<BR>
<BR>
<PRE>
CORBA::ULong CORBA::Any::NP_length() const
</PRE>is supplied. This member function returns the length of the value
returned by the <TT>CORBA::Any::value()</TT> member function. It may be
necessary to use this function if the Any's value is to be stored in a
file.<BR>
<BR>

<H5>Threads and type Any.</H5>
Inserting and extracting simultaneously from the same Any (in 2
different threads) is undefined behaviour.<BR>
<BR>
Extracting simultaneously from the same Any (in 2 or more different
threads) also leads to undefined behaviour. It was decided not to
protect the Any with a mutex, as this condition should rarely arise,
and adding a mutex would lead to performance penalties.<BR>
<BR>
<A NAME="toc49"></A>
<H2>9.3&nbsp;&nbsp; TypeCode in omniORB</H2>This section contains some notes on the use and behaviour of TypeCode
in omniORB<BR>
<BR>

<H5>TypeCodes in IDL.</H5>When using TypeCodes in IDL, note that they are defined in the CORBA
scope. Therefore, <TT>CORBA::TypeCode</TT> should be used. Example:<BR>
<BR>
<PRE>
// IDL 5
struct Test5 {
  long length;
  CORBA::TypeCode desc;
};
</PRE>
<H5>orb.idl</H5>Inclusion of the file <TT>orb.idl</TT> in IDL using
<TT>CORBA::TypeCode</TT> is optional. An empty <TT>orb.idl</TT> file is
provided for compatibility purposes.<BR>
<BR>

<H5>Generating TypeCodes for constructed types.</H5>To generate a TypeCode for constructed types, specify the
<TT>-Wba</TT> command-line flag when running omniidl. This will
generate a <TT>_tc_</TT> TypeCode describing the type, at the same
scope as the type (as per the CORBA 2.3 specification). Example:<BR>
<BR>
<PRE>
// IDL 6
struct Test6 {
  double a;
  sequence&lt;long&gt; b;
};
</PRE>A TypeCode, <TT>_tc_Test6</TT>, will be generated to describe the
struct <TT>Test6</TT>. The operations defined in the TypeCode interface
(see section 10.7 of the CORBA 2.3 specification&nbsp;[<A HREF="omniORB014.html#corba23-spec"><CITE>OMG99</CITE></A>])
can be used to query the TypeCode about the type it represents.<BR>
<BR>

<H5>TypeCode equality.</H5>The behaviour of <TT>CORBA::TypeCode::equal()</TT> member function from
omniORB 2.8.0 onwards is different from pre-omniORB 2.8.0 releases.
In summary, the pre-omniORB 2.8.0 is close to the semantics of the new
<TT>CORBA::TypeCode::equivalent()</TT> member function. Details are as
follows:<BR>
<BR>
The <TT>CORBA::TypeCode::equal()()</TT> member function will now return true
only if the two TypeCodes are <EM>exactly</EM> the same.
<TT>tk_alias</TT> TypeCodes are included in this comparison, unlike the
comparison made when values are extracted from an Any (see section on
Any, above).<BR>
<BR>
In pre-omniORB 2.8.0 releases, equality test would ignore the optional
fields when one of the fields in the two typecodes is empty. For
example, if one of the TypeCodes being checked is a <TT>tk_struct</TT>,
<TT>tk_union</TT>, <TT>tk_enum</TT>, or <TT>tk_alias</TT>, and has an
empty repository ID parameter, then the repository ID parameter will
be ignored when checking for equality. Similarly, if the <TT>name</TT>
or <TT>member_name</TT> parameters of a TypeCode are empty strings,
they will be ignored for equality checking purposes. This is because a
CORBA 2 ORB does not have to include these parameters in a TypeCode
(see the Interoperability section of the CORBA 2
specification&nbsp;[<A HREF="omniORB014.html#corba2-spec"><CITE>OMG96</CITE></A>]). Note that these (optional)
parameters are included in TypeCodes generated by omniORB.<BR>
<BR>
Since CORBA 2.3, the issue of TypeCode equality has been clarified.
There is now a new member <TT>CORBA::TypeCode::equivalent()</TT> which
provides the semantics of the <TT>CORBA::TypeCode::equal()</TT> as
implemented in omniORB releases prior to 2.8.0. So from omniORB 2.8.0
onwards, the <TT>CORBA::TypeCode::equal()</TT> function has been
changed to enforce strict equality. The pre-2.8.0 behaviour can be
obtained with <TT>equivalent()</TT>.<BR>
<BR>
<A NAME="toc50"></A>
<H2>9.4&nbsp;&nbsp; Source Listing</H2>
<H3>9.4.1&nbsp;&nbsp; anyExample_impl.cc</H3><PRE>
// anyExample_impl.cc - This is the source code of the example used in
//                      Chapter 9 "Type Any and TypeCode" of the omniORB
//                      users guide.
//
//                      This is the object implementation.
//
// Usage: anyExample_impl
//
//        On startup, the object reference is printed to cerr as a
//        stringified IOR. This string should be used as the argument to 
//        anyExample_clt.
//

#include &lt;iostream.h&gt;
#include &lt;anyExample.hh&gt;

class anyExample_i : public POA_anyExample {
public:
  inline anyExample_i() {}
  virtual ~anyExample_i() {}
  virtual CORBA::Any* testOp(const CORBA::Any&amp; a);
};

CORBA::Any* anyExample_i::testOp(const CORBA::Any&amp; a)
{
  cout &lt;&lt; "Any received, containing: " &lt;&lt; endl;

#ifndef NO_FLOAT
  CORBA::Double d;
#endif

  CORBA::Long l;
  const char* str;

  testStruct* tp;

  if (a &gt;&gt;= l) {
    cout &lt;&lt; "Long: " &lt;&lt; l &lt;&lt; endl;
  }
#ifndef NO_FLOAT
  else if (a &gt;&gt;= d) {
    cout &lt;&lt; "Double: " &lt;&lt; d &lt;&lt; endl;
  }
#endif
  else if (a &gt;&gt;= str) {
    cout &lt;&lt; "String: " &lt;&lt; str &lt;&lt; endl;
  }
  else if (a &gt;&gt;= tp) {
    cout &lt;&lt; "testStruct: l: " &lt;&lt; tp-&gt;l &lt;&lt; endl;
    cout &lt;&lt; "            s: " &lt;&lt; tp-&gt;s &lt;&lt; endl;
  }
  else {
    cout &lt;&lt; "Unknown value." &lt;&lt; endl;
  }

  CORBA::Any* ap = new CORBA::Any;

  *ap &lt;&lt;= (CORBA::ULong) 314;

  cout &lt;&lt; "Returning Any containing: ULong: 314\n" &lt;&lt; endl;
  return ap;
}

//////////////////////////////////////////////////////////////////////

int main(int argc, char** argv)
{
  try {
    CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB3");

    CORBA::Object_var obj = orb-&gt;resolve_initial_references("RootPOA");
    PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);

    anyExample_i* myobj = new anyExample_i();

    PortableServer::ObjectId_var myobjid = poa-&gt;activate_object(myobj);

    obj = myobj-&gt;_this();
    CORBA::String_var sior(orb-&gt;object_to_string(obj));
    cerr &lt;&lt; "'" &lt;&lt; (char*)sior &lt;&lt; "'" &lt;&lt; endl;

    myobj-&gt;_remove_ref();

    PortableServer::POAManager_var pman = poa-&gt;the_POAManager();
    pman-&gt;activate();

    orb-&gt;run();
    orb-&gt;destroy();
  }
  catch(CORBA::SystemException&amp;) {
    cerr &lt;&lt; "Caught CORBA::SystemException." &lt;&lt; endl;
  }
  catch(CORBA::Exception&amp;) {
    cerr &lt;&lt; "Caught CORBA::Exception." &lt;&lt; endl;
  }
  catch(omniORB::fatalException&amp; fe) {
    cerr &lt;&lt; "Caught omniORB::fatalException:" &lt;&lt; endl;
    cerr &lt;&lt; "  file: " &lt;&lt; fe.file() &lt;&lt; endl;
    cerr &lt;&lt; "  line: " &lt;&lt; fe.line() &lt;&lt; endl;
    cerr &lt;&lt; "  mesg: " &lt;&lt; fe.errmsg() &lt;&lt; endl;
  }
  catch(...) {
    cerr &lt;&lt; "Caught unknown exception." &lt;&lt; endl;
  }
  return 0;
}
</PRE>
<H3>9.4.2&nbsp;&nbsp; anyExample_clt.cc</H3><PRE>
// anyExample_clt.cc -  This is the source code of the example used in 
//                      Chapter 9 "Type Any and TypeCode" of the omniORB 
//                      users guide.
//
//                      This is the client.
//
// Usage: anyExample_clt &lt;object reference&gt;
//

#include &lt;iostream.h&gt;
#include &lt;anyExample.hh&gt;

static void invokeOp(anyExample_ptr&amp; tobj, const CORBA::Any&amp; a)
{
  CORBA::Any_var bp;

  cout &lt;&lt; "Invoking operation." &lt;&lt; endl;
  bp = tobj-&gt;testOp(a);

  cout &lt;&lt; "Operation completed. Returned Any: ";
  CORBA::ULong ul;

  if (bp &gt;&gt;= ul) {
    cout &lt;&lt; "ULong: " &lt;&lt; ul &lt;&lt; "\n" &lt;&lt; endl;
  }
  else {
    cout &lt;&lt; "Unknown value." &lt;&lt; "\n" &lt;&lt; endl;
  }
}

static void hello(anyExample_ptr tobj)
{
  CORBA::Any a;

  // Sending Long
  CORBA::Long l = 100;
  a &lt;&lt;= l;
  cout &lt;&lt; "Sending Any containing Long: " &lt;&lt; l &lt;&lt; endl; 
  invokeOp(tobj,a);
    
  // Sending Double
#ifndef NO_FLOAT
  CORBA::Double d = 1.2345;
  a &lt;&lt;= d;
  cout &lt;&lt; "Sending Any containing Double: " &lt;&lt; d &lt;&lt; endl; 
  invokeOp(tobj,a);
#endif
  
  // Sending String
  const char* str = "Hello";
  a &lt;&lt;= str;
  cout &lt;&lt; "Sending Any containing String: " &lt;&lt; str &lt;&lt; endl;
  invokeOp(tobj,a);
    
  // Sending testStruct  [Struct defined in IDL]
  testStruct t;
  t.l = 456;
  t.s = 8;
  a &lt;&lt;= t;
  cout &lt;&lt; "Sending Any containing testStruct: l: " &lt;&lt; t.l &lt;&lt; endl;
  cout &lt;&lt; "                                   s: " &lt;&lt; t.s &lt;&lt; endl;
  invokeOp(tobj,a);
}

//////////////////////////////////////////////////////////////////////

int main(int argc, char** argv)
{
  try {
    CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB3");

    if( argc != 2 ) {
      cerr &lt;&lt; "usage:  anyExample_clt &lt;object reference&gt;" &lt;&lt; endl;
      return 1;
    }

    CORBA::Object_var obj = orb-&gt;string_to_object(argv[1]);
    anyExample_var ref = anyExample::_narrow(obj);
    if( CORBA::is_nil(ref) ) {
      cerr &lt;&lt; "Can't narrow reference to type anyExample (or it was nil)."
    &lt;&lt; endl;
      return 1;
    }
    hello(ref);

    orb-&gt;destroy();
  }
  catch(CORBA::COMM_FAILURE&amp; ex) {
    cerr &lt;&lt; "Caught system exception COMM_FAILURE -- unable to contact the "
         &lt;&lt; "object." &lt;&lt; endl;
  }
  catch(CORBA::SystemException&amp;) {
    cerr &lt;&lt; "Caught a CORBA::SystemException." &lt;&lt; endl;
  }
  catch(CORBA::Exception&amp;) {
    cerr &lt;&lt; "Caught CORBA::Exception." &lt;&lt; endl;
  }
  catch(omniORB::fatalException&amp; fe) {
    cerr &lt;&lt; "Caught omniORB::fatalException:" &lt;&lt; endl;
    cerr &lt;&lt; "  file: " &lt;&lt; fe.file() &lt;&lt; endl;
    cerr &lt;&lt; "  line: " &lt;&lt; fe.line() &lt;&lt; endl;
    cerr &lt;&lt; "  mesg: " &lt;&lt; fe.errmsg() &lt;&lt; endl;
  }
  catch(...) {
    cerr &lt;&lt; "Caught unknown exception." &lt;&lt; endl;
  }
  return 0;
}
</PRE><HR WIDTH="50%" SIZE=1><DL>
<DT><A NAME="note20" HREF="#text20"><FONT SIZE=5>1</FONT></A><DD> In pre-omniORB 2.8.0
releases, omniORB performs an equality test and will ignore any alias
TypeCodes (<TT>tk_alias</TT>) when making this comparison. The
semantics is similar to the <TT>equivalent()</TT> test in the TypeCode
interface of CORBA 2.3.
</DL>
<HR>
<A HREF="omniORB008.html"><IMG SRC ="previous_motif.gif" ALT="Previous"></A>
<A HREF="index.html"><IMG SRC ="contents_motif.gif" ALT="Contents"></A>
<A HREF="omniORB010.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>