Dynamic Invocation Interface
Dynamic Invocation Interface
The Dynamic Invocation Interface lets your client applications use any registered object without having to first link the client stubs created for that object by the IDL compiler. With the DII, your client application can dynamically build requests for any object interface that has been stored in the Interface Repository. Even recently registered object can be accessed by a client application using the DII. Your object implementations are not required to provide any extra code to handle DII requests. Steps for Dynamic Invocation
There are five steps that a client follows for dynamic invocation.
Repository
and then invoke the methods defined by the Repository
class to locate object implementations. Table 9-1 shows the various types of objects that can be contained in the IR. A complete description of this class can be found in the VisiBroker for
C++ Reference Guide
.
The following section lists the objects that can be stored in the Interface Repository. The object type is given first followed by the description.
Repository
Class.
class CORBA {
class Repository : public Container {
Contained_ptr lookup_id(const char * search_id);
PrimitiveDef_ptr get_primitive(PrimitiveKind kind);
StringDef_ptr create_string(ULong bound);
SequenceDef_ptr create_sequence(CORBA::ULong bound,
IDLType_ptr element_type);
ArrayDef_ptr create_array(ULong length,
IDLType_ptr element_type);
};
...
};
Library
interface and obtain information about the add_book
operation.
#include <lib_client.hh>main(int argc, char *const *argv)
{
CORBA::Boolean ret;
// Initialize the ORB
CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);
// Declare the library object
library_var library_object;
// Declare an interface repository pointer
CORBA::Repository_var rep_object;
try {
// Attempt to bind to the interface repository
rep_object = CORBA::Repository::_bind();
}
// Check for errors
catch(const CORBA::Exception& excep) {
cout << "Error binding to interface repository" << endl;
return(0);
}
// Locate the add_book operation definition. Can the operation be
// located without first locating the interface?
CORBA::Contained_var add_req = rep_object
->lookup_id("Library::add_book");
try {
// Bind to the library object.
library_object = library::bind();
}
// Check for errors
catch(const CORBA::Exception& excep) {
cout << "Error binding to library object" << endl;
return(0);
}
// Create a request, initializing the operation name.
Request_var req = library_object->_request(add_req->name());
...
}
Request
must be created to represent the method invocation. This Request
is written to a buffer and sent to the object implementation. When your client application uses client stubs, this processing occurs transparently. Client applications that use the DII must create and send the Request themselves. Figure 9-1 shows the Request
class.class CORBA {Theclass 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();
...
};
};
target
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. The initialization of the remaining properties is covered in "Initializing a DII Request" and "Initializing Requests from an OperationDef" later in this document. A complete description of this class can be found in the VisiBroker for C++ Reference Guide.
Request
object. The following example shows the methods offered by the Object
class.
class CORBA {You can use the _create_request method to create aclass Object {
...
Status _create_request(Context_ptr ctx,
const char * operation,
NVList_ptr arg_list,
NamedValue_ptr result,
Request_ptr request,
Flags req_flags);
Request_ptr _request(Identifier operation);
...
};
};
Request
object, initializing the Context
, the operation
name, the argument list to be passed and the result. The request parameter points to the Request
object that was created for this operation. The req_flags
must be set to OUT_LIST_MEMORY if one or more of the arguments in the arg_list
are output parameters.You can also use the
_request
method to create a Request
object, specifying only the operation name. You must then perform the rest of the initialization manually.
Context
object contains a list of properties, stored as NamedValue
objects, that are passed to the object implementation as part of the Request
. These properties represent information that would otherwise be difficult to communicate to the object implementation. A complete description of this class can be found in the VisiBroker for
C++ Reference Guide
.
class CORBA {class Context {
public:
const char *context_name() const;
CORBA::Context_prt 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;
};
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 the arguments. This pointer can then be used to set the names and values of each of the arguments.
class NVList {public:
Long count() const;
NamedValue_ptr add(Flags);
NamedValue_ptr add_item(const char *name, Flags);
NamedValue_ptr add_value(const char *name, const Any&, Flags);
NamedValue_ptr item(Long);
Status remove(Long);
Status free_out_memory();
};
Any
class. A complete description of this class can be found in the VisiBroker for C++ Reference Guide.
class NamedValue {The following section lists thepublic:
const char *name() const;
Any *value() const;
Flags flags() const;
};
NamedValue
class methods. The method is given first followed by the description.name()
Returns a pointer to the name of the item that you can then use to initialize the name.
value()
Returns a pointer to an
Any
object representing the item's value that you can then use to initialize the value. For more information, see "The Any Class" on page 9-11.
flags()
TypeCode
that defines the object's type and a pointer to the value associated with the object. Methods are provide to construct, copy and destroy an object as well as initialize and query the object's properties. In addition, streaming operators are provided to write the object to a stream. A complete description of this class can be found in the VisiBroker for C++ Reference Guide.
class Any{
public:
Any();
Any(const Any&);
Any(TypeCode_ptr tc, void *value, Boolean release=0);
~Any();
Any& operator=(const Any&);
// Overloaded operators for all data types
void operator<<=(Short);
void operator<<=(UShort);
void operator<<=(Long);
void operator<<=(ULong);
...
TypeCode_ptr type();
const void *value() const;
static Any_ptr _nil();
static Any_ptr _duplicate(Any *ptr);
static void _release(Any *ptr);
// Streaming operators to write Anys to stdout, etc.
ostream& operator<<(ostream&, const Any&);
istream& operator>>(istream& strm, Any& any);
istream& operator>>(istream& strm, Any_ptr& any);
...
}
Any
class. TypeCode
objects have a kind property and parameter list property. A complete description of this class can be found in the VisiBroker for
C++ Reference Guide
.
TC_null
tk_null
No parameters.
TC_void
tk_void
No parameters.
TC_short
tk_short
No parameters.
TC_long
tk_long
No parameters.
TC_ushort
tk_ushort
No parameters.
TC_ulong
tk_ulong
No parameters.
TC_float
tk_float
No parameters.
TC_double
tk_double
No parameters.
TC_boolean
tk_boolean
No parameters.
TC_char
tk_char
No parameters.
TC_octet
tk_octet
No parameters.
TC_any
tk_any
No parameters.
TC_TypeCode
tk_TypeCode
No parameters.
TC_Principal
tk_Principal
No parameters.
TC_Object
tk_objref
interface_id
Structure (const generated)
tk_struct
struct-name, {member, TypeCode}
Union (const generated)
tk_union
union-name, switch TypeCode, {label-value, member-name, TypeCode}
Enum (const generator)
tk_enum
{enum-name, enum-id}
TC_string
tk_string
maxlen
Sequence (const generator)
tk_sequence
TypeCode, maxlen
Array (const generator)
tk_array
TypeCode, length
The following section lists TypeCode
constants for IDL data types. The type is given first followed by the name.TypeCode_ptr
_tc_null
TypeCode_ptr
_tc_void
TypeCode_ptr
_tc_short
TypeCode_ptr
_tc_long
TypeCode_ptr
_tc_ushort
TypeCode_ptr
_tc_ulong
TypeCode_ptr
_tc_float
TypeCode_ptr
_tc_double
TypeCode_ptr
_tc_boolean
TypeCode_ptr
_tc_char
TypeCode_ptr
_tc_octet
TypeCode_ptr
_tc_Any
TypeCode_ptr
_tc_TypeCode
TypeCode_ptr
_tc_Principal
TypeCode_ptr
_tc_Object
TypeCode_ptr
_tc_string
TypeCode_ptr
_tc_NamedValue
Request
class provides several methods for sending the request, once it has been properly initialized. The simplest of these is the invoke
method which sends the request and blocks waiting for a response before returning to your client application. The non-blocking method send_deferred
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
send_oneway
method can be used to send a oneway request. Oneway requests do not involve a response being sent from the object implementation.The
result
method returns a pointer to a NamedValue
object that represents the return value.The following example shows how to send a DII request.
...
// Assumes that req has been set to Request
// Create TypeCode for structure
CORBA::StructMemberSeq members;
members.length(2);
members[0].name = (const char *)"author";
members[0].type = CORBA::TypeCode::_duplicate(CORBA::_tc_string);
members[1].name = (const char *)"title";
members[1].type = CORBA::TypeCode::_duplicate(CORBA::_tc_string);
bookTypeCode = orb->create_struct_tc(
"book", "book", members);
// Write out author and title to a MarshalOutBuffer
CORBA::MarshalOutBuffer buf;
buf << argv[1]; // Author
buf << argv[2]; // Title
bookValue.replace(bookTypeCode, buf);
// Get Argument list from request.
CORBA::NVList_var arguments = req->arguments();
arguments->add_value("book", bookValue, CORBA::ARG_IN);
// Set result
// NOTE: All parameters types (IN, OUT, INOUT and RETURN) need
// to be set so that DII knows the data types of all
// arguments.
CORBA::Boolean ret=0;
CORBA::NamedValue_var result(req->result());
CORBA::Any_var resultAny(result->value());
resultAny->replace(CORBA::_tc_boolean, &result);
// Execute the function
req->invoke();
CORBA::Environment_var env = req->env();
if ( env->exception() )
cout << "Exception occured" << endl;
else {
// Get the return value;
ret = *(CORBA::Boolean *)resultAny->value();
}
cout << "Return value from invoke: " << (int)ret << endl;
return(1);
}
Request
objects can be created using RequestSeq
, defined in the CORBA::ORB
class and shown in Figure 9-12. A sequence of requests can be sent using the 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.
If the requests in the sequence are 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.poll_next_response
can be used to determine if a response has been received from the server. This method returns one if one or more responses are available. This method returns zero if there are no responses available.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 application to block, use the poll_next_response
method to determine when a response is available.
class CORBA {class ORB {
...
typedef sequence<Request_ptr> RequestSeq;
Status send_multiple_requests_oneway(const RequestSeq &);
Status send_multiple_requests_deferred(const RequestSeq &);
Boolean poll_next_response();
Status get_next_response();
...
};
};