| 
                •     
               | Bridges or adapters between script environments and CORBA objects. For example, a script calls your bridge, passing object and method identifiers and parameter values. Your bridge constructs and issues a dynamic request, receives the result, and returns it to the scripting environment. Such a bridge could not use static invocation because its developer could not know in advance what kinds of objects the script environment would want to invoke. | 
        
       
      
        
          
            | 
                •     
               | Generic object testers. For example, a client takes an arbitrary object identifier, looks up its interface in the interface repository (see “Using Interface Repositories” ), and then invokes each of its methods with artificial argument values. Again, this style of generic tester could not be built with static invocation. | 
        
       
      
      Clients must pass valid arguments in DII requests. Failure to do so can produce unpredictable results, including server crashes. Although it is possible to dynamically type-check parameter values with the interface repository, it is expensive. For best performance, ensure that the code (for example, script) that invokes a DII-using client can be trusted to pass valid arguments.
 
      
      
      
      
      
      
      
      
      A Request object represents one invocation of one method on one CORBA object. If you want to invoke two methods on the same CORBA object, or the same method on two different objects, you need two 
Request objects. To invoke a method you first need the 
target reference, an object reference representing the CORBA object. Using the target reference, you create a 
Request, populate it with arguments, send the 
Request, wait for the reply, and obtain the result from the 
Request.
 
      There are two ways to create a Request. The simpler way is to invoke the target object's 
_request method, which all CORBA objects inherit. This does not, in fact, invoke the target object. You pass 
_request the IDL name of the method you intend to invoke in the 
Request, for example, “
get_balance.” To add argument values to a 
Request created with 
_request, you invoke the 
Request's 
add_value method for each argument required by the method you intend to invoke. To pass one or more 
Context objects to the target, you must add them to the 
Request with its 
ctx method.
 
      Although not intuitively obvious, you must also specify the type of the Request's result with its 
result method. For performance reasons, the messages exchanged between the VisiBroker ORBs do not contain type information. By specifying a place holder result type in the 
Request, you give the VisiBroker ORB the information it needs to properly extract the result from the reply message sent by the target object. Similarly, if the method you are invoking can raise user exceptions, you must add place holder exceptions to the 
Request before sending it.
 
      The more complicated way to create a Request object is to invoke the target object's 
_create_request method, which, again, all CORBA objects inherit. This method takes several arguments which populate the new 
Request with arguments and specify the types of the result and user exceptions, if any, that it may return. To use the 
_create_request method you must have already built the components that it takes as arguments. The potential advantage of the 
_create_request method is performance. You can reuse the argument components in multiple 
_create_request calls if you invoke the same method on multiple target objects.
 
      
      There are two overloaded forms of the _create_request method: one that includes 
ContextList and 
ExceptionList parameters, and one that does not. If you want to pass one or more 
Context objects in your invocation, and/or the method you intend to invoke can raise one or more user exceptions, you must use the 
_create_request method that has the extra parameters.
 
      
      The target method's arguments, result, and exceptions are each specified in special objects called Anys. An 
Any is a generic object that encapsulates an argument of any type. An 
Any can hold any type that can be described in IDL. Specifying an argument to a 
Request as an 
Any allows a 
Request to hold arbitrary argument types and values without making the compiler complain of type mismatches. (The same is true of results and exceptions.)
 
      An Any consists of a 
TypeCode and a value. A value is just a value, and a 
TypeCode is an object that describes how to interpret the bits in the value (that is, the value's type). Simple 
TypeCode constants for simple IDL types, such as 
long and 
Object, are built into the header files produced by the 
idl2cpp compiler. 
TypeCodes for IDL constructed types, such as 
structs, 
unions, and 
typedefs, have to be constructed. Such 
TypeCodes can be recursive because the types they describe can be recursive.
 
      Consider a struct consisting of a 
long and a 
string. The 
TypeCode for the 
struct contains a 
TypeCode for the 
long and a 
TypeCode for the 
string. The 
idl2cpp compiler will generate 
TypeCodes for the constructed types in an IDL file if the compiler is invoked with the 
-type_code_info option. However, if you are using the DII, you need to obtain 
TypeCodes at runtime. You can get a 
TypeCode at runtime from an interface repository (see 
“Using Interface Repositories”) or by asking the VisiBroker ORB to create one by invoking 
ORB::create_struct_tc or 
ORB::create_exception_tc.
 
      If you use the _create_request method, you need to put the 
Any-encapsulated target method arguments in another special object called an 
NVList. No matter how you create a 
Request, its result is encoded as an 
NVList. Everything said about arguments in this paragraph applies to results as well. “NV” stands for named value, and an 
NVList consists of a count and number of items, each of which has a name, a value, and a flag. The name is the argument name, the value is the 
Any encapsulating the argument, and the flag denotes the argument's IDL mode (for example, 
in or 
out). The result of 
Request is represented a single named value.
 
      
      Once you create and populate a Request with arguments, a result type, and exception types, you send it to the target object. There are several ways to send a 
Request,
 
      
      
        
          
            | 
                •     
               | More complex, but not blocking, is the Request's send_deferred  method. This is an alternative to using threads for parallelism. For many operating systems the send_deferred  method is more economical than spawning a thread. | 
        
       
      
        
          
            | 
                •     
               | If your motivation for using the send_deferred method is to invoke multiple target objects in parallel, you can use the VisiBroker ORB object's send_multiple_requests_deferred  method instead. It takes a sequence of Request  objects. | 
        
       
      
        
          
            | 
                •     
               | Use the Request's send_oneway  method if, and only if, the target method has been defined in IDL as oneway . | 
        
       
      
      
      If you send a Request by calling its 
invoke method, there is only one way to get the result: use the 
Request object's 
env method to test for an exception, and if none, extract the 
NamedValue from the 
Request with its 
result method. If you used the 
send_oneway method, then there is no result. If you used the 
send_deferred method, you can periodically check for completion by calling the 
Request's 
poll_response method which returns a code indicating whether the reply has been received. If, after polling for a while, you want to block waiting for completion of a deferred send, use the 
Request's 
get_response method.
 
      If you have sent Requests with the 
send_multiple_requests_deferred method, you can find out if a particular 
Request is complete by invoking that 
Request's 
get_response method. To learn when any outstanding 
Request is complete, use the VisiBroker ORB's 
get_next_response method. To do the same thing without risking blocking, use the VisiBroker ORB's 
poll_next_response method.
 
      
      
      
        
          
            | 
                1	
               | Make sure the-type_code_info option is passed to the idl  compiler so that type codes are generated for IDL interfaces and types. | 
        
       
      
      
        
          
            | 
                3	
               | Create a Request object for the target object. | 
        
       
      
      
      
      
      
      
      
      Compile these example programs with the VIS_INCLUDE_IR flag, and add the typecode generation option.
 
      
      
      The code sample below shows how your client program can use the bind method offered by the VisiBroker ORB object to bind to any object by specifying its name. This method returns a generic 
CORBA::Object.
 
      . . .
CORBA::Object_var account;
try {
   // initialize the ORB.
   CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv);
} catch (const CORBA::Exception& e)
   cout << "Failure during ORB_init" << endl;
   cout << e << endl;
}
. . .
try {
   // Request ORB to bind to object supporting the account interface.   
account = orb->bind("IDL:Account:1.0");
} catch (const CORBA::Exception& excep)
   cout << "Error binding to account" << endl;
   cout << excep << endl;
}
cout << "Bound to account object" << endl;
. . .
 
      
      When your client program invokes a method on an object, a Request object is created to represent the method invocation. The 
Request object is written, or 
marshaled, to a buffer and sent to the object implementation. When your client program uses client stubs, this processing occurs transparently. Client programs that wish to use the DII must create and send the 
Request object themselves.
 
      
      There is no constructor for this class. The Object's 
_request method or 
Object's 
_create_request method are used to create a 
Request object.
 
      
      The following code sample shows the Request class. The 
target of the request is set implicitly from the object reference used to create the 
Request. The name of the 
operation must be specified when the 
Request is created.
 
      class Request {
   public:
      CORBA::Object_ptr 
target() const;
      const char* 
operation() const;
      CORBA::NVList_ptr 
arguments();
      CORBA::NamedValue_ptr 
result();
      CORBA::Environment_ptr 
env();
      void    
ctx(CORBA::Context_ptr ctx);
      CORBA::Context_ptr 
ctx() const;
      CORBA::Status 
invoke();
      CORBA::Status 
send_oneway();
      CORBA::Status 
send_deferred();
      CORBA::Status 
get_response();
      CORBA::Status 
poll_response();
      . . .
   };
};
 
      
      
      
      class Object {
   . . .
   CORBA::Request_ptr 
_request(Identifier operation);
   CORBA::Status 
_create_request(
      CORBA::Context_ptr ctx,
      const char *operation,
      CORBA::NVList_ptr arg_list,
      CORBA::NamedValue_ptr result,
      CORBA::Request_ptr request,
      CORBA::Flags req_flags);
   CORBA::Status 
_create_request(
      CORBA::Context_ptr ctx,
      const char *operation,
      CORBA::NVList_ptr arg_list,
      CORBA::NamedValue_ptr result,
      CORBA::ExceptionList_ptr eList,
      CORBA::ContextList_ptr ctxList,
      CORBA::Request_out request,
      CORBA::Flags req_flags);
   . . .
};
 
      
      You can use the _create_request method to create a 
Request object, initialize the 
Context, the operation name, the argument list to be passed, and the result. Optionally, you can set the 
ContextList for the request, which corresponds to the attributes defined in the request's IDL. The request parameter points to the 
Request object that was created for this operation.
 
      
      The code sample in “Example of creating a Request object” shows the use of the 
_request method to create a 
Request object, specifying only the operation name. After creating a float request, calls to its 
add_in_arg method add an input parameter Account name. Its result type is initialized as an Object reference type via a call to 
set_return_type method. After a call has been made, the return value is extracted with the result's call to the 
result method. The same steps are repeated to invoke another method on an Account Manager instance with the only difference being in-parameters and return types.
 
      The req, an 
Any object is initialized with the desired account 
name and added to the request's argument list as an input argument. The last step in initializing the request is to set the 
result value to receive a 
float.
 
      
      A Request object maintains ownership of all memory associated with the operation, the arguments, and the result so you should never attempt to free these items. The following code sample is an example of creating a request object.
 
      . . .
CORBA::NamedValue_ptr result;
CORBA::Any_ptr 
resultAny;
CORBA::Request_var 
req;
CORBA::Any 
customer;
. . .
try {   
req = account->_request("balance");
   // Create argument to request   
customer <<= (const char *) name;
   CORBA::NVList_ptr arguments = req->arguments();
   arguments->add_value("customer", customer, CORBA::ARG_IN);
   // Set result   
result = req->result();
   resultAny = result->value();
   resultAny->replace(CORBA::_tc_float, &result);
} catch(CORBA::Exception& excep) {
. . .
 
      
      Though it is not used in the example program, the Context object can be used to contain a list of properties, stored as 
NamedValue objects, that will be passed to the object implementation as part of the 
Request. These properties represent information that is automatically communicated to the object implementation.
 
      
            const char *context_name() const;
      CORBA::Context_ptr          
parent();
      CORBA::Status 
create_child(const char *name, CORBA::Context_ptr&);
      CORBA::Status 
set_one_value(const char *name, const CORBA::Any&);
      CORBA::Status 
set_values(CORBA::NVList_ptr);
      CORBA::Status 
delete_values(const char *name);
      CORBA::Status 
get_values(
            const char *start_scope,
            CORBA::Flags,
            const char *name,
            CORBA::NVList_ptr&) const;
};
 
      
      The arguments for a Request are represented with a NVList object, which stores name-value pairs as 
NamedValue objects. You can use the 
arguments method to obtain a pointer to this list. This pointer can then be used to set the names and values of each of the arguments.
 
      
      Always initialize the arguments before sending a Request. Failure to do so will result in marshaling errors and may even cause the server to abort.
 
      
      This class implements a list of NamedValue objects that represent the arguments for a method invocation. Methods are provided for adding, removing, and querying the objects in the list. The following code sample is an example of the NVList class:
 
      class NVList {
   public:
      . . .
      CORBA::Long 
count() const;
      CORBA::NamedValue_ptr 
add(Flags);
      CORBA::NamedValue_ptr 
add_item(const char *name, CORBA::Flags flags);
      CORBA::NamedValue_ptr 
add_value(
            const char *name,
            const CORBA::Any *any,
            CORBA::Flags flags);
      CORBA::NamedValue_ptr 
add_item_consume(char *name, CORBA::Flags flags);
      CORBA::NamedValue_ptr 
add_value_consume(
            char *name,
            CORBA::Any *any,
            CORBA::Flags flags);
      CORBA::NamedValue_ptr 
item(CORBA::Long index);
      CORBA::Status 
remove(CORBA::Long index);
      . . .
};
 
      
      This class implements a name-value pair that represents both input and output arguments for a method invocation request. The NamedValue class is also used to represent the result of a request that is returned to the client program. The 
name property is simply a character string and the 
value property is represented by an 
Any class. The following code sample is an example of the NamedValue class.
 
      class NamedValue {
   public:
      const char *
name() const;
      CORBA::Any *
value() const;
      CORBA::Flags 
flags() const;
};
 
      
      
      
      
      Objects of this class have a pointer to a TypeCode that defines the contained object's type and a pointer to the contained object. Methods are provided to construct, copy, and release an object as well as initialize and query the object's value and type. In addition, streaming operators methods are provided to read and write the object from and to a stream. The following code sample is an example of defining this class.
 
      class Any {
   public:
      . . .
      CORBA_TypeCode_ptr 
type();
      void type(CORBA_TypeCode_ptr tc);
      const void 
*value() const;
      static CORBA::Any_ptr 
_nil();
      static CORBA::Any_ptr 
_duplicate(CORBA::Any *ptr);
      static void 
_release(CORBA::Any *ptr);
      . . .
}
 
      
      This class is used by the Interface Repository and the IDL compiler to represent the type of arguments or attributes. TypeCode objects are also used in a 
Request object to specify an argument's type, in conjunction with the 
Any class.
 
      TypeCode objects have a 
kind and parameter list property. The following code sample is an example of the 
TypeCode class.
 
      
      
        
        
          |  |  | 
        
          |  | repository_id, interface_name | 
        
          |  | repository_id, alias_name , TypeCode | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  | repository_id, enum-name , enum-id1 , enum-id2 , ... enum-idn | 
        
          |  | repository_id, exception_name , StructMembers | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  | repository_id, interface_id | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  | repository_id, struct-name , {member1 , TypeCode1} , {membern , TypeCoden} | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
        
          |  | repository_id, union-name , switch TypeCode ,{label-value1 , member-name1 , TypeCode1} , {labell-valuen , member-namen , TypeCoden} | 
        
          |  |  | 
        
          |  | repository_id, value_name , boxType | 
        
          |  | repository_id, value_name , typeModifier , concreteBase , members | 
        
          |  |  | 
        
          |  |  | 
        
          |  |  | 
      
      
      class _VISEXPORT CORBA_TypeCode {
  public:
      . . .
    // For all CORBA_TypeCode kinds
    CORBA::Boolean equal(CORBA_TypeCode_ptr tc) const;
    CORBA::Boolean 
equivalent(CORBA_TypeCode_ptr tc) const;
    CORBA_TypeCode_ptr 
get_compact_typecode() const;
    CORBA::TCKind 
kind() const // . . .
    // For tk_objref, tk_struct, tk_union, tk_enum, tk_alias and tk_except
    virtual const char* id() const; // raises(BadKind);
    virtual const char *name() const; // raises(BadKind);
    // For tk_struct, tk_union, tk_enum and tk_except
    virtual CORBA::ULong member_count() const; 
          // raises((BadKind));
    virtual const char *member_name(CORBA::ULong index) const;
          // raises((BadKind, Bounds));
    // For tk_struct, tk_union and tk_except
    virtual CORBA_TypeCode_ptr member_type(CORBA::ULong index) const;
          // raises((BadKind, Bounds));
    // For tk_union
    virtual CORBA::Any_ptr member_label(CORBA::ULong index) const;
          // raises((BadKind, Bounds));
    virtual CORBA_TypeCode_ptr discriminator_type() const;
          // raises((BadKind));
    virtual CORBA::Long default_index() const; 
          // raises((BadKind));
    // For tk_string, tk_sequence and tk_array
    virtual CORBA::ULong length() const; 
          // raises((BadKind));
    // For tk_sequence, tk_array and tk_alias
    virtual CORBA_TypeCode_ptr content_type() const; 
          // raises((BadKind));
    // For tk_fixed
    virtual CORBA::UShort fixed_digits() const; 
          // raises (BadKind)
    virtual CORBA::Short fixed_scale() const;  
          // raises (BadKind)
    // for tk_value
    virtual CORBA::Visibility 
       member_visibility(CORBA::ULong index) const;
          // raises(BadKind, Bounds);
    virtual CORBA::ValueModifier type_modifier() const; 
          // raises(BadKind);
    virtual CORBA::TypeCode_ptr concrete_base_type() const; 
          // raises(BadKind);
};
 
      
      The Request class, as discussed in 
“Creating and initializing a request”, provides several methods for sending a request once it has been properly initialized.
 
      
      The simplest way to send a request is to call its invoke method, which sends the request and waits for a response before returning to your client program. The 
return_value method returns a pointer to an 
Any object that represents the return value. The following code sample shows how to send a request with invoke.
 
      
      
      A non-blocking method, send_deferred, is also provided for sending operation requests. It allows your client to send the request and then use the 
poll_response method to determine when the response is available. The 
get_response method blocks until a response is received. The following codes show how these methods are used. The following sample shows you how to use the 
send_deferred and 
poll_response methods to send a deferred DII request.
 
      
      
      The send_oneway method can be used to send an asynchronous request. Oneway requests do not involve a response being returned to the client from the object implementation.
 
      
      A sequence of DII Request objects can be created using array of Request objects. A sequence of requests can be sent using the VisiBroker ORB methods send_multiple_requests_oneway or 
send_multiple_requests_deferred. If the sequence of requests is sent as oneway requests, no response is expected from the server to any of the requests.
 
      
      . . .
// Create request to balance
try {
   req1 = account->_request("balance");
   // Create argument to request   
customer1 <<= (const char *) "Happy";
   CORBA::NVList_ptr arguments = req1->arguments();
   arguments->add_value("customer", customer1, CORBA::ARG_IN);
   // Set result
   . . .
} catch(const CORBA::Exception& excep) {
   cout << "Error while creating request" << endl;
   cout << excep << endl;
}
// Create request2 to slowBalance
try {   
req2 = account->_request("slowBalance");
   // Create argument to request   
customer2 <<= (const char *) "Sleepy";
   CORBA::NVList_ptr arguments = req2->arguments();
   arguments->add_value("customer", customer2, CORBA::ARG_IN);
   // Set result
   . . .
} catch(const CORBA::Exception& excep) {
   cout << "Error while creating request" << endl;
   cout << excep << endl;
}
// Create request sequence
CORBA::Request_ptr reqs[2];
reqs[0] = (CORBA::Request*) req1;
reqs[1] = (CORBA::Request*) req2;
CORBA::RequestSeq reqseq((CORBA::ULong)2, 2, (CORBA::Request_ptr *) reqs);
// Send the request
try {   
orb->send_multiple_requests_deferred(reqseq);
   cout << "Send multiple deferred calls are made..." << endl;
} catch(const CORBA::Exception& excep) {
. . .
 
      
      When a sequence of requests is sent using send_multiple_requests_deferred, the 
poll_next_response and 
get_next_response methods are used to receive the response the server sends for each request.
 
      The VisiBroker ORB method poll_next_response can be used to determine if a response has been received from the server. This method returns 
true if there is at least one response available. This method returns 
false if there are no responses available.
 
      The VisiBroker ORB method get_next_response can be used to receive a response. If no response is available, this method will block until a response is received. If you do not wish your client program to block, use the 
poll_next_response method to first determine when a response is available and then use the 
get_next_response method to receive the result. The following code sample shows an example of sending multiple requests and receiving the results:
 
      class CORBA {
   class 
ORB {
      . . .
      typedef sequence <Request_ptr> 
RequestSeq;
      void 
send_multiple_requests_oneway(const RequestSeq &);
      void 
send_multiple_requests_deferred(const RequestSeq &);
      Boolean 
poll_next_response();
      Status 
get_next_response();
      . . .
   };
};
 
      
      One source of the information needed to populate a DII Request object is an interface repository (IR) (see 
, “Using Interface Repositories”). The following example uses an interface repository to get obtain the parameters of an operation. Note that the example, atypical of real DII applications, has built-in knowledge of a remote object's type (
Account) and the name of one of its methods (
balance). An actual DII application would get that information from an outside source, for example, a user.
 
      
      
        
          
            | 
                •     
               | Looks up the Account's balance  method in the IR and builds an operation list from the IR OperationDef . | 
        
       
      
      
      // acctdii_ir.C
// This example illustrates IR and DII
#include <iostream.h>
#include "corba.h"
int main(int argc, char* const* argv) {
   CORBA::ORB_ptr orb;
   CORBA::Object_var account;
   CORBA::NamedValue_var result;
   CORBA::Any_ptr resultAny;
   CORBA::Request_var req;
   CORBA::NVList_var operation_list;
   CORBA::Any customer;
   CORBA::Float acct_balance;
try {
    // use argv[1] as the account name, or a default.
    CORBA::String_var name;
    if (argc == 2)
       name = (const char *) argv[1];
    else
       name = (const char *) "Default Name";
   try {
      // Initialize the ORB.
      orb = CORBA::ORB_init(argc, argv);
   } catch(const CORBA::Exception& excep) {
      cout << "Failure during ORB_init" << endl;
      cout << excep << endl;
      exit(1);
   }
   cout << "ORB_init succeeded" << endl;
   // Unlike traditional binds, this bind is called off of "orb"
   // and returns a generic object pointer based on the interface name
   try {
 account = orb->bind("IDL:Account:1.0");
   } catch(const CORBA::Exception& excep) {
      cout << "Error binding to account" << endl;
      cout << excep << endl;
      exit(2);
   }
   cout << "Bound to account object" << endl;
   // Obtain Operation Description for the "balance" method of
   // the Account
   try {
      CORBA::InterfaceDef_var intf = account->_get_interface();
      if (intf == CORBA::InterfaceDef::_nil()) {
         cout << "Account returned a nil interface definition. " << endl;
         cout << "  Be sure an Interface Repository is running and" << endl;
         cout << "  properly loaded" << endl;
         exit(3);
      } 
CORBA::Contained_var oper_container = intf->lookup("balance");
 CORBA::OperationDef_var oper_def =
      CORBA::OperationDef::_narrow(oper_container);
      orb->create_operation_list(oper_def, operation_list.out());
   } catch(const CORBA::Exception& excep) {
      cout << "Error while obtaining operation list" << endl;
      cout << excep << endl;
      exit(4);
   }
   // Create request that will be sent to the account object
   try {
      // Create placeholder for result
      orb->create_named_value(result.out());
      resultAny = result->value();
      resultAny->replace( CORBA::_tc_float, &result);
      // Set the argument value within the operation_list 
CORBA::NamedValue_ptr arg = operation_list->item(0);
 CORBA::Any_ptr anyArg = arg->value();
      *anyArg <<= (const char *) name;
      // Create the request 
 account->_create_request(CORBA::Context::_nil(), 
            "balance",
            operation_list,
            result,
            req.out(),
            0);
   } catch(const CORBA::Exception& excep) {
      cout << "Error while creating request" << endl;
      cout << excep << endl;
      exit(5);
   }
   // Execute the request
   try {
      req->invoke();
      CORBA::Environment_ptr env = req->env();
      if ( env->exception() ) {
         cout << "Exception occurred" << endl;
         cout << *(env->exception()) << endl;
         acct_balance = 0;
      } else  {
         // Get the return value; 
acct_balance = *(CORBA::Float *)resultAny->value();
      }
   } catch(const CORBA::Exception& excep) {
      cout << "Error while invoking request" << endl;
      cout << excep << endl;
      exit(6);
   }
   // Print out the results
   cout << "The balance in " << name << "'s account is $";
   cout << acct_balance << "." << endl;
} catch ( const CORBA::Exception& excep ) {
   cout << "Error occurred" << endl;
   cout << excep << endl;
}