Although the orb library RWreqistream and RWreqostream classes insulate developers from having to read and write directly to the CORBA::Request, it is still necessary to write the actual insertion and extraction operators for the CORBA::Request.
The insertion operator, operator<<(), marshals the opaque object's state into a CORBA::Request for transmission to a remote process. The extraction operator, operator>>(), unmarshals an opaque object which is received from a remote process in a CORBA::Request.
For our example Book class, these operators look like this:
CORBA::Request &operator<<(CORBA::Request &req, const Book *bk) { RWreqostream orbostrm(req); orbostrm << *bk; return req; } CORBA::Request &operator<<(CORBA::Request &req, Book *&bk) { RWreqostream orbostrm(req); orbostrm << *bk; return req; } CORBA::Request &operator>>(CORBA::Request &req, Book *&bk) { RWreqistream orbistrm(req); bk = new Book; orbistrm >> *bk; return req; }
As you can imagine, writing these operators for every class you want to pass as an opaque type would be tedious. To counter this, the orb library provides two macros that create the CORBA::Request insertion and extraction operations for you:
RWDEFINE_OPAQUE is used for classes that define insertion and extraction operators for the Tools.h++ virtual iostreams.
RWDEFINE_OPAQUE_COLLECTABLE is used for classes that inherit from the Tools.h++ RWCollectable class and implement the saveGuts(RWvostream&) and restoreGuts(RWvistream&) operations.
Since many Rogue Wave classes already define virtual stream operations, or inherit from RWCollectable and implement the saveGuts() and restoreGuts() operations, they can be passed easily as opaque types using RWDEFINE_OPAQUE and RWDEFINE_OPAQUE_COLLECTABLE.
These definitions must be provided for both the client and the server. You can either call the macro in the same source file as the opaque C++ class, or you can create an include file that just contains the macro call. Then include the file in both the client and server executables.
Given the Library interface, assume that Book inherits from RWCollectable and implements the saveGuts and restoreGuts methods:
virtual void Book::saveGuts(RWvostream &vos); virtual void Book::restoreGuts(RWvistream &vis);
Also assume that the Borrower class implements (as friend functions) the insertion and extraction operators for virtual streams. For example:
RWvostream &operator<<(RWvostream &vostream, const Borrower &bwr); RWvistream &operator>>(RWvistream &vistream, Borrower &bwr);
Given these assumptions, two simple C++ files could be written to implement the operations, required by the ORB, for those types to be passed as opaque objects. For Book, you could write a file called bookio.cpp, as follows:
#include <rw/toolpro/opaqueio.h> /* RWDEFINE_OPAQUE definitions */ #include "book.h" /* Book class definition */
RWDEFINE_OPAQUE_COLLECTABLE(Book)
For Borrower, you could write a similar file, called borrowio.cpp:
#include <rw/toolpro/opaqueio.h> /* RWDEFINE_OPAQUE definitions */ #include "borrower.h" /* Borrower class definition */
RWDEFINE_OPAQUE(Borrower)
These files would then be compiled and linked into both the client and the server portions of the program.
©Copyright 2000, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.