Go to the previous, next section.

# Using ILU with CORBA 2.0 C++

## Warning

The CORBA 2.0 C++ stubber is limited in functionality. The stubber is only currently working for Visual C++ (sans nested modules and pickles/anys support). This is very new software - it has received very limited testing, and the stubber receives little support from the current team.

## Introduction

This chapter describes the use of ILU with C++ in a manner compliant with the CORBA 2.0 C++ language mapping specification. (see `http://www.omg.org/corba/corbiiop.htm`) The use of ILU's original C++ support is deprecated.

Any function or type which is not part of the CORBA 2.0 specification has the prefix 'ilu'. It should be understood that use of 'ilu' prefixed functionality is not portable to other (non-ILU) CORBA implementations.

Some arguments or return values of functions (e.g. char*) have storage management requirements. Basically this revolves around whether the caller retains or gets ownership of the parameter and is therefore responsible for eventually releasing it, or if ILU takes or retains ownership, where it will be released at ILU's discretion. Any function parameter that becomes owned by ILU is marked with the comment /* ILUowned */ Any return value (or 'out' parameter) that remains under the ownership of ILU is similarly marked. Anything not so marked is not ILU's responsibility.

Note that ILU support for C++ does rely on having argument prototypes, all C++ library functions, and the capabilities of the C++ pre-processor.

## Mapping ILU ISL to C++

The CORBA 2.0 C++ chapters 15 though 18 describes the mapping of OMG IDL to C++. For those elements of ISL for which there is a direct counterpart in IDL, the ISL component is mapped just as the IDL component is. Those ISL concepts with no IDL counterpart (marked with a '`-`' in the table below) have a mapping separately described in a following section.

### ISL to IDL Correspondences

         ISL                    IDL
         -------------------------------------
         INTEGER                long
         SHORT INTEGER          short
         LONG INTEGER           -
         CARDINAL               unsigned long
         SHORT CARDINAL         unsigned short
         LONG CARDINAL          -
         BYTE                   octet
         BOOLEAN                boolean
         REAL                   double
         SHORT REAL             float
         LONG REAL              -
         CHARACTER              -
         SHORT CHARACTER        char
         PICKLE                 Any
         ARRAY                  array
         SEQUENCE               sequence
         RECORD                 struct
         UNION                  union
         OPTIONAL               -
         ENUMERATION            enum
         OBJECT                 object
         CString                string
         SEQUENCE OF CHARACTER  -
         EXCEPTION              -, exception
         INTERFACE              module

### ISL Specific Mappings

The following table describes the mappings for ISL types that have no IDL counterparts. The C++ column gives the mapping modulo indirection and/or 'const' qualification dictated by parameter directionality (i.e., IN vs OUT vs INOUT vs return values).

         ISL                    C++
         --------------------------------------------------------------
         LONG INTEGER           iluLongInteger
         LONG CARDINAL          iluLongCardinal
         LONG REAL              iluLongReal
         CHARACTER              iluCharacter
         OPTIONAL X             X* for operation parameters;
                                'managed X*' for embedded types.
         SEQUENCE OF CHARACTER  iluCharacter*
         EXCEPTION              Any ISL exception that is
                                not a RECORD, maps to a subclass of
                                CORBA::UserException, that has a _value()
                                member function which returns a value of
                                the type associated with the exception.

### Correspondence between C++ Types and Kernel Types

To provide a consistent naming scheme, in many cases, a type defined in the ILU kernel has been typedeffed to appear in C++ as the corresponding type name without the intervening underscore, and with the following letter capitalized, e.g. typedef ilu_cardinal iluCardinal;

### C++ Classes Produced for an Object

The mapping for an ISL Object 'A' produces 3 C++ classes:

1. The A C++ class, which has pure virtual member function declarations for each of A's methods. For each ISL Object supertype Si of ISL Object A, the C++ class A 'public virtual' inherits from the Si C++ class. If the ISL Object A has no supertypes, the A class 'public virtual' inherits from the iluObject class. [NOTE that an object described in IDL will implicity inherit from CORBA::Object (which in turn inherits from iluObject). The idl2isl translator automatically adds ilu.CORBA-Object as a SUPERTYPE.] This basically creates a C++ class hierarchy that is isomorphic to the ISL object type hierarchy, with each method being declared pure virtual. We refer to this hierarchy as the 'abstract object hierarchy'.

2. The A_surrogate C++ class, which has virtual member function declarations for each of ISL Object A's non inherited methods. These member functions transfer requests to the true object. For each ISL Object supertype Si of ISL Object A, the C++ class A_surrogate 'public virtual' inherits from the Si_surrogate C++ class, and then 'public virtual' inherits from the C++ class A. (If the ISL Object A has no supertypes, the A_surrogate class 'public virtual' inherits only from the C++ class A.) This basically creates a C++ 'surrogate object hierarchy' that is isomorphic to the abstract object type hierarchy, with the addition that each X_surrogate class also inherits from its counterpart in the 'abstract object hierarchy'.

3. An A_var C++ class as prescribed by the CORBA C++ mapping.

This mapping allows servers to be developed that do not contain surrogate stub code (if they don't need it), and also prevents the situation where a server method override is forgotten, resulting in surrogate stub code being called as it it were 'true' code.

For each ISL Object 'A' for which a true side implementation is to be developed, the true side implementer should define a class A_impl that inherits virtually from the C++ class A, and implements the actual true methods as member functions (in whatever manner is appropriate). The implementer is free to use delegation, implementation inheritance, whatever - the only restriction is that if a class B_impl inherits implementation from a class X, and class X inherits from a class in the abstract object hierarchy, (e.g. when X is A_impl), then X's inheritance from the abstract object hierarchy must be 'public virtual'.

Each produced C++ class e.g. A, will have a constructor C++: A ( char* pc_instance_handle, ilu_Server& r_an_ilu_server = iluServer::GetDefaultServer(), ILUCPP_BOOL b_within_object_table = ILUCPP_FALSE ) : iluObject ( A::m_ILUClassRecord, pc_instance_handle, r_an_ilu_server, b_within_object_table).

### Misc. Mapping Details

#### Unions

In IDL, Union arms all have names, in ISL, the names may not be specified. If a name isn't specified for an arm, the name the stubber produces is the arm's typename, prefixed with '_', and suffixed with '_arm'.

For example,

    TYPE someuniontype = short cardinal UNION
            bar = 0, 1 END,
            integer = DEFAULT
    END;

would produce the C++ names _bar_arm, and _integer_arm to reference the bar and integer arms.

#### Optionals

For procedure parameters, an ISL `OPTIONAL` type maps either to the same C++ type as its base type, if that base type is represented with an C++ pointer type, or to a pointer to that base type, if it is not represented with a C++ pointer type.

Additionally, all `OPTIONAL` types T have an associated C++ T_var.

For non-parameters (i.e., `RECORD` members, `ARRAY` and `SEQUENCE` elements) an ISL `OPTIONAL` type maps to a 'managed pointer', analagous to the mapping for non-parameter ISL `OBJECT` (CORBA `interface`) and ISL `SEQUENCE OF SHORT CHARACTER` (CORBA `string`). (This 'managed pointer' behaves similarly to T_var; however, CORBA does not allow compliant applications to use 'managed pointer' types directly, as the actual type is implementation-specific)

The following ISL and C++ code fragments illustrate:

         ISL

         TYPE SomeType   = ...
         TYPE MyOptional = OPTIONAL SomeType;

    	 TYPE MyRec = RECORD
    	     member: MyOptional
    	 END;

    	 TYPE MyArray = ARRAY OF 10 MyOptional;
    	     member: MyOptional
    	 END;

         C++

    	 ...

         MyRec          myRec;
    	 MyArray        myArray;
    	 SomeType       st;
    	 SomeType*      stPtr;
    	 MyOptional     myOptional;  // MyOptional is equivalent to SomeType*
    	 MyOptional_var stVar;

    	 ...

    	 myRec.member = myArray[0];        // free old myRec.member, deep copy
    	 myArray[1]   = stVar;             // free old myArray[1], deep copy
    	 myRec.member = stPtr;             // free old myRec.member, assume ownership
    	 myRec.member = myOptional;        // free old myRec.member, assume ownership

    	 myRec.member = &st;               // ILLEGAL - can't free &st
    	 myRec.member = new SomeType(st);  // OK; free old myRec.member, assume ownership

    	 stPtr = myArray[2];               // Simple pointer assignment, no copy
    	 stVar = myRec.member;             // free old stVar, deep copy

The lifetime of `recA.member` and each `myArray[n]` are tied to recA and myArray, respectively; when an optional-containing variable goes out of scope or is destroyed, its optional members/elements are freed. Thus, the assignment `myRec.member = &st` in the example above is illegal and can lead to calamitous results when an attempt is made to free &st.

#### Exceptions

Any ISL exception that is not a RECORD, maps to a subclass of CORBA::UserException, that has a _value() member function which returns a value of the type associated with the exception.

#### ISL Asynchronous Methods

In IDL, methods may be `ASYCHRONOUS`. Asynchronous methods cannot have return values or raise exceptions. Hence, they result in a C++ member function declared to return void.

#### ISL Functional Methods

In IDL, methods may be `FUNCTIONAL`. In the C++ mapping, `FUNCTIONAL` is ignored. The ability to create custom C++ surrogates allows the implementation to decide what and how caching may be implemented on any method, as well as perform any other sorts of message 'filtering'.

#### ISL Collectible Objects

An ISL object being declared `COLLECTIBLE` has not effect on the mapping per-se. It will however cause ILU to adjust an object's reference count based on interest or dis-interest from clients.

#### Inheritence from CORBA::Object

If an ISL Object A has no supertypes, the A class 'public virtual' inherits from the iluObject class. An object described in IDL will implicity inherit from CORBA::Object (which in turn inherits from iluObject). (The idl2isl translator automatically adds ilu.CORBA-Object as a SUPERTYPE.) So, if you define an object in ISL, and do not explicitly declare ilu.CORBA-Object as a SUPERTYPE, you will not have the member functions of CORBA::Object available since you do not inherit from it.

#### Portability and Mapping Variations

The CORBA 2.0 C++ mapping allows for variations in the mapping depending on the C++ compilers support for Name Spaces, Exception Handling, and Run-Time Type information.

The ILU CORBA 2.0 C++ mapping implementation assumes that the C++ compiler supports exceptions. We also assume that the compiler supports RTTI should someone want to do narrowing within the exception hierarchy. [Given that ILU does not provide a Dynamic Invocation Interface, there's no real need to narrow exceptions anyway.]

During the configuration phase of ILU installation (or for Windows, per the definitions in ``ILUSRC/runtime/kernel/iluwin.h'`) a determination is made as to whether or not to use namespaces, nested classes or underscores for IDL modules, based on the C++ compiler in use. [This can be overridden with the configuration option --with-cplusplus-mapping= switch to config.] This results in a C++ runtime that is constructed with one of these approaches in mind. Should a user decide to use a different mapping, this can be done by setting appropriate switches to the stubber, but you must bear in mind that the C++ runtime needs to be in correspondence, since the selection radically changes the names seen by a linker. Based on our knowledge (as of the date of this writing), of the degree of support/bugs for namespaces and nested classes, the following describes the IDL module mapping based on compiler:

C++ Compiler Module Mapping

         Compiler                 Mapping
         ---------------------------------------
         Microsoft Visual C++     underscores
         SunPro                   nested classes
         Gnu                      nested classes

To portably reference things in a interface when the stubber is directed to produce portable code, the stubber generates two macros, one for referring to things from outside the namespace (e.g. when defining a member function), and another for inside the namespace (e.g. inside a class declaration). The names of these macros are the interface name, and the interface name with a '_' (underscore) suffix. These macros expand to some other macros that are defined in the cppportability.hpp file.

To refer to things in the CORBA interface, one uses the CORBA macro. For example, CORBA(Boolean) b_my_result = ILUCPP_TRUE;

Because of possible variations in compiler support for Booleans, CORBA(Boolean) is defined as ILUCPP_BOOL, where ILUCPP_BOOL is defined as either an int (with ILUCPP_TRUE and ILUCPP_FALSE #defined as 1 and 0), or as a bool (with ILUCPP_TRUE and ILUCPP_FALSE #defined as true and false).

## Concepts

### Servers and Ports

In ILU there is a concept of an 'server object'. In the kernel this is the ilu_Server, which in the C++ runtime is encapsulated asn an `iluServer` object. This 'server' effectively forms a 'scope' in which true objects reside. This is why for example, and object lookup requires both the 'server' ID, and the object's instance handle - both are needed to uniquely denote an object.

Now a server has some number of 'ports'. A port is basically a means of communicating with the objects inside a server, using a particular combination of protocol and transport. For example, when create an `iluServer`, the constructor for `iluServer` automatically adds a port for the communication protocol and transport specified as constructor arguments. We can call `iluServer::iluAddPort` to have additional ports added. For example we may want to be able to communicate with the objects using `sunrpc` over `tcp/ip`, as well as `http` over `tcp/ip`. The iluServer has a notion of a default port. This is initially one as specified during construction, but this can be changed if when calling `iluServer::iluAddPort` we specify that this should become the default port. The default port is the one used when we ask for contact information for an object - that is, if we get the string binding handle for an object, the contact information in that string will reflect the default server port.

### Object Tables

True objects may either be created ahead of time, or on an 'as needed' basis, i.e. when a call comes in involving them. The 'as needed' situation is made possible by 'object tables'. An `iluServer` may have associated with it (at construction time) an `iluObjectTable` object. When a call comes involving an object in that `iluServer` that the ILU doesn't already know about, the `iluObjectTable` object's `iluObjectOfInstanceHandle` gets called. It is the job of this function to create and return a new object with that instance handle. How it does this is specific to your application - it may read object state off a disk for example. In any event, one thing this function must do is ensure that when it calls the true objects constructor, that it sets the constructor's b_within_object_table argument to true. (Otherwise, internal locking constraints will be violated). While in the `iluObjectOfInstanceHandle` function, the associated `iluServer`'s lock is held, and if the resulting object is expected to be of a COLLECTIBLE type, the global kernel mutex "gcmu" is also held. The fact that these locks are held somewhat restricts what an application can do inside this mapping procedure.

### Threading

The ILU C++ support may be initialized to run in either threaded or non-threaded mode. In non threaded mode, a call to `iluServer::iluRun` member function results in a call to ILU's 'mainloop'. The mainloop basically sits waiting for an incoming request. When one comes in, the request is invoked. If the implementation of the invoked method makes a call to some other remote object, the mainloop is recursively entered while awaiting a reply. This allows additional requeste to come in and get serviced, preventing deadlock.

When intialized to run in threaded mode, ILU will run one thread for each incoming connection. Note that there may be multiple connections for a particular port (either from different clients, or from the same client who needed another connection because all the ones it had so far were busy at the time). In the case of a non-concurrent protocol (sunrpc, http, courier), the connection thread receives an incoming request, processes it itself, and then waits for the next request. In the case of a concurrent protocol (csunrpc, iiop), the connnection thread receives an incoming request, spawns a worker thread to carry out the request, and immediately goes back to waiting for more incoming requests.

The ILU C++ provides no special concurrency control for methods in your objects (to do so would be presumptive on our part). The method implementor must put appropriate locking in place if it is possible that multiple threads (or recursive mainloop invocations) might be running 'in' an object simultaneously.

### Custom Surrogates

A surrogate is an object that is used to represent a remote object. When a method is invoked on a surrogate, the methods implementation in the surrogate transfers the call to the true object, and returns the result of this call, thus providing location transparency. There are times however when it is useful to have the surrogate's method implementation do more than just forward the call to the true object. An application may want a surrogate method implementation that caches the results of calls (potentially reducing network overhead), perform transformations on arguments, output diagnostic information, or whatever.

To facilitate this, the ILU C++ support allows an implementation to supply a function that is called when a surrogate for a particular object type is needed. The function `iluCppRuntime::iluSetSurrogateCreator` tells the C++ runtime what function to call when a surrogate for an object of the specified class is needed. This allows an implementation to subclass off a surrogate class, and write a new surrogate creation function that creates an instance of this new subclass. Call `iluCppRuntime::iluSetSurrogateCreator` after you've performed initialization, but before you do any operations which might create a surrogate of the specified class. It basically overwrites the default surrogate creation function set up by the surrogate stubs. It returns the old surrogate creator function, or `NULL` if was previously no surrogate creator for that class.

A surrogate creator function should at the minimum create an instance of a surrogate, call the instances member function iluAssociateKernelObject passing the `iluKernelObject`, and then return a pointer to the new instance.

### String Binding Handle Manipulation

A String Binding Handle is a textual representation of an object reference. It contains the object's server id, instance id, information about how to contact the object, as well as other information. ILU C++ provides the functions `iluCppRuntime::iluFormSBH`, `iluCppRuntime::iluFormSBHUsingContactInfo`, and `iluCppRuntime::iluParseSBH` for constructing and parsing string binding handles. An object may be obtained from a string binding handle using `iluObject::iluStringToObject` and the string bindign handle of an object may be obtained by calling the `iluObjectToString` member function.

### Simple Binding

When creating a service, there needs to be some way for clients to find out about the service. ILU C++ provides a simple mechanism to achieve this. Objects may be published, looked up, and their publications withdrawn using the appropriate member functions (`iluPublish`, `iluLookup`, `iluWithdraw`).

### Object Activation

An true object is initially 'Active', which means that its ISL (or IDL as the case may be) defined methods may be invoked on it from outside its process (or from another language within that same process). An object may be made unavailable to outside calls, i.e. marked 'inactive' by calling its iluDeactivate member function. It may may be reactivated by calling its iluActivate member function.

An object is initially available from the outside until it is deactivated Objects that are involved in a call (i.e. sent or received as arguments, or the object the method is being invoked on) need to be protected from deletion for the duration of that involvement (for example, you don't want some thread deleting a true object when it's currently the target of a method call). The C++ runtime keeps track of what objects are involved in a call, and will attempt to prevent them from being deleted until the call is completed.

The application programmer needs to assist in this by calling, in the most specific destructor, iluDeactivate (inherited virtually from `iluObject`). iluDeactivate blocks any further incoming calls involving the object, and wait for any ongoing calls using the object to complete. Next the destructor should perform any object specific cleanup. Finally, the destructor in `iluObject` will break the association between the kernel object and this object, allowing the kernel object to be potentially freed.

### Security

A client may set the Passport to be used on outgoing calls by creating and setting up an `iluPassport,` and then passing the passport in a call to iluPassport::iluSetPassport. This sets the passport to be used in the thread that made the call - i.e. `iluPassport` are on a per thread basis. Note that before your thread exits, you should either call iluSetPassport(`NULL`), or delete the `iluPassport` in use (assuming it's only in use for a single thread). The `iluPassport` (if any) currently setup for a thread can be retrieved by calling iluPassport::iluGetPassport.

A Server may obtain the `iluPassport` of the caller (if any) of a method by using the iluPassport::iluGetCallerPassport() function.

A `iluServer` may be constructed to use a particular identity by specifying a `iluPassport` as a constructor argument. This identity is used to identify the principal offering the service.

### Static Initialization

The C++ Runtime normally relies on the static initializers in the files that the stubber generates to place initialization functions onto internal lists so that they will be invoked when the application calls iluCppRuntime::Initialize. However, it is not guaranteed by the ANSI C++ that static initializers are called upon the loading of a compilation unit. We have only had a report of one compiler that did not run the static initializers at load time (in fact, it was reported that it did not run them ever! - bug!?). We have observed static initialization at load time in Visual C++, SunPro and GNU compilers. In the event that you end up using a compiler that does not call the static initializers at load time, you can use the stubber defined initialization macros that are generated in the common header file for each interface.

(It should be pointed out that the CORBA 2.0 C++ Runtime does not suffer from the static initializer issues that plagued ILU's original C++ support. No ILU calls are actually made until iluCppRuntime::iluInitialize is called, allowing one to set up different mainloops, etc.)

## Building an Application

### Running the Stubber

To generate CORBA 2.0 C++ stubs from an ISL file, use the program cpp2-stubber. The stubber has the following usage:

         Usage: cpp2-stubber [arguments] Islfile [ISLFILE ...]
    		 [arguments] can be any of the following:
    		 [-nu|-underscores]
    		 [-np|-portable]
    		 [-nn|-nested]
    		 [-ns|-namespaces]

The switches can be used to direct the stubber to produce code that using a specific module mapping, or portable module mapping. The default is whatever is found appropriate during the configuration phase of ILU installation (see "Portability and Mapping Variations"). Note that generating a specific (non-portable) mapping that does not match the platform default, is likely to cause errors at link time due to naming differences.

### Stubber Generated Files

For an interface `Foo` the stubber generates:

``Foo-cpp.hpp'` which contains the classes for the abstract object hierarchy, as well as any other declarations needed by both client and server.

``Foo-cpp.cpp'`, which contains any definitions needed by both client and server

``Foo-cppsurrogate.hpp'` which contains the classes for the surrogate object hierarchy, as well as any other declarations needed just by a client. This file #includes Foo-cpp.hpp

``Foo-cppsurrogate.cpp'`, which contains any definitions needed just by a client. This file #includes Foo-cppsurrogate.hpp

``Foo-cpptrue.hpp'` which contains any declarations needed just by a server. This file #includes Foo-cpp.hpp

``Foo-cpptrue.cpp'`, which contains any definitions needed just by a server. This file #includes Foo-cpptrue.hpp. All header files use the usual #ifdef method to prevent multiple inclusions.

A client only will #include Foo-cppsurrogate.hpp, and link with ``Foo-cpp.o'` and ``Foo-cppsurrogate.o'`

A server only will #include Foo-cpptrue.hpp, and link with ``Foo-cpp.o'` and ``Foo-cpptrue.o'`

A client and server will #include Foo-cpptrue.hpp, #include Foo-cppsurrogate.hpp, and and link with ``Foo.o'`, ``Foo-cpptrue.o'`, and ``Foo-cppsurrogate.o'`

### Server Basics

The basic steps in creating a simple server application are as follows (assuming we have a ISL file called ``foo.isl'`, describing an interface 'foo' with an object type 'bar'):

1. Run the C++ stubber on ``foo.isl'`, e.g. cpp2-stubber foo.isl

2. In your implementation file, e.g. ``servermain.cpp'`, include the true side header file, e.g. #include "foo-cpptrue.hpp".

3. Define an implementation class that inherits public virtual from foo::bar. e.g.

       	class foo_bar_impl : public virtual foo(bar) { ... };

4. In the implementation class, provide a constructor that receives an instance handle and an `iluServer` as arguments, and calls the `iluObject` constructor appropriately, e.g.

       	foo_bar_impl::foo_bar_impl(char* pc_instance_handle, iluServer& r_an_ilu_server) :
       		iluObject(foo(bar)::m_ILUClassRecord, pc_instance_handle, r_an_ilu_server) {}

5. In the implementation class declaration, declare a virtual destructor. e.g. virtual foo_bar_impl::~foo_bar_impl();

6. Define the virtual destructor of the implementation class that (at the minimum) makes a call to iluDeactivate as the first thing it does, e.g.

       	  foo_bar_impl::~foo_bar_impl() {
       		  iluDeactivate();
       		  // other app specific things that may need to be done
       	  }

7. In the implementation class declaration, declare the virtual member functions that will implement the method(s), e.g.

       	virtual CORBA(Boolean) zap( CORBA(Long)  inarg, CORBA(Octet)&  inoutarg, CORBA(Double)& outarg )
       		throw (CORBA(SystemException), foo(zapexception));

8. Define the virtual member functions that implement the method(s), e.g.

       	CORBA(Boolean) foo_bar_impl::zap( CORBA(Long)  inarg,
       		  CORBA(Octet)&  inoutarg,
       		  CORBA(Double)& outarg )
       		  throw (CORBA(SystemException), foo(zapexception)) {
       		  // do whatever must be done
       		  }

9. In for example 'main()', Call the runtime initialization function, passing an argument specifying whether or not to set up for threaded operation, e.g.

       		// Set up the runtime for threaded operation
       		iluCppRuntime::iluInitialize(ILUCPP_TRUE);

10. Create an `iluServer`. e.g.

        	iluServer server ("MyFooBarServerOnMyHost");

11. Create a true object in that server, e.g.

        	p_true_foo_bar = new foo_bar_impl("foo_bar_instance_0", server);

12. Publish the true foo::bar object, e.g.

        	p_true_foo_bar->iluPublish()

13. Run the server, e.g.

         	server.iluRun();

14. Compile your server application code, ``foo-cpp.cpp'` and ``foo-cpptrue.cpp'`, and link the resulting object files with the C++ runtime library (``libilu-cpp2.a'` on UNIX, and ``ilucpp2.lib'` on Win32) and the ILU kernel library (``lib.a'` on UNIX, and ``ilu32.lib'` on Win32).

### Client Basics

The basic steps in creating a simple client application are as follows (assuming we have a ISL file called ``foo.isl'`, describing an interface 'foo' with an object type 'bar'):

1. Run the C++ stubber on foo.isl, e.g. cpp2-stubber foo.isl

2. In your implementation file, e.g. ``clientmain.cpp'`, include the surrogate side header file, e.g. #include "foo-cppsurrogate.hpp".

3. In for example 'main()', call the runtime initialization function, passing an argument specifying whether or not to set up for threaded operation, e.g.

       	// Set up the runtime for threaded operation
       	iluCppRuntime::iluInitialize(ILUCPP_TRUE);

4. Lookup an object, e.g.

       	foo(bar_var) mybar_var = foo(bar)::iluLookup ("foo_bar_instance_0", "MyFooBarServerOnMyHost");

5. Invoke a method, e.g.

       	try {
       		bool_return_value = mybar_var->zap(inarg, inoutarg, outarg);
       	}
       	catch (const foo(zapexception)& the_exception) {
       		/* do whatever */
       	}
       	catch (const CORBA(SystemException)& the_exception) {
       		/* do whatever */
       	}
       	catch (...) {
       		/* do whatever */
       	}

6. Compile your client application code, ``foo-cpp.cpp'` and ``foo-cppsurrogate.cpp'`, and link the resulting object files with the C++ runtime library (``libilu-cpp2.a'` on UNIX, and ``ilucpp2.lib'` on Win32) and the ILU kernel library (``lib.a'` on UNIX, and ``ilu32.lib'` on Win32).

## Relevant examples

The ILU examples directory contains two examples that use the CORBA 2.0 C++ mapping. See cpp2foo, and test1. The cpp2foo example illustrates a lot: object tables; collectible; custom surrogates; lookups; anys; return, in, inout, and out of most types; use of _vars; and more;

## Runtime Classes

### Overview

The classes of interest to the application programmer are listed below. Nearly all non-static member functions are virtual to allow creative overrides (at your own risk of course).

`iluCppRuntime` - Abstract class that provides various static member functions that the application can use to control the runtime's behavior.

`iluServer` - Provides the C++ view of a kernel server object.

`iluObject` - The most base class for all ILU C++ objects. All objects inherit either directly or indirectly from this class.

`iluObjectTable` - An abstract C++ class for developers to derive from to provide Object Tables.

`iluPassport` - encapsulates ilu_Passport functionality

`iluGSS` - encapsulates GSS functionality

`iluMainLoop` - An abstract base class for developers to derive from to create their own main loop.

`iluWString_var` Class - analog to CORBA(String_var) only for ILU Characters

(See ``ILUSRC/runtime/cpp2/ilu.hpp'` and ``ILUSRC/runtime/cpp2/corba.hpp'` for more complete descriptions.)

### iluCppRuntime

An Abstract class that provides various static member functions that the application can use to control the runtime's behavior. `iluCppRuntime` is not meant to ever be subclassed.

#### iluCppRuntime - Initialization Related

C++: static void iluCppRuntime::iluInitialize ( ILUCPP_BOOL b_use_native_threads = `ILUCPP_FALSE` )

Initializes the C++ runtime for use. Also calls all the functions (typically interface initialization functions in generated stubs) that are on the C++ Runtime's initialization function list (see iluCppRuntime::iluAddInitializationFunction).

iluCppRuntime::iluInitialize's use depends on your use of threading:

1. No threading at all - just call iluCppRuntime::iluInitialize().

2. Using ILU's native operating system (OS) thread support - call iluCppRuntime::iluInitialize(ILUCPP_TRUE).

3. Your own thread package - call iluCppRuntime::iluSetForkProcedure, iluCppRuntime::iluSetNonNativeThreadIDFunction then call the ILU kernel functions ilu_SetWaitTech, and ilu_SetLockTech appropriately, call iluMainLoop::iluSetMainLoop, then call iluCppRuntime::iluInitialize().

C++: static void iluCppRuntime::iluAddInitializationFunction ( iluPFunctionInitializer pf_initialize )

Adds an initialization function onto the runtime's list of (typically interface initialization) functions to call when iluCppRuntime::iluInitialize is called. iluPFunctionInitializer is typedeffed as

C++: void (* iluPFunctionInitializer ) ( )

C++: static void iluCppRuntime::iluSetNonNativeThreadIDFunction ( iluNonNativeThreadIDFunction p_thread_id_function )

When running non-native threaded, this should be called (before initialization) set to the function that will return a thread unique `iluCardinal` id of the current thread. iluNonNativeThreadIDFunction is typedeffed as

C++: iluCardinal (* iluNonNativeThreadIDFunction )( )

C++: static iluPFunctionSurrogateCreator iluCppRuntime::iluSetSurrogateCreator ( iluClass surrogate_class, iluPFunctionSurrogateCreator pfunction_surrogate_creator )

Tells the C++ runtime what function to call when a surrogate for an object of the specified class is needed. This allows an implementation to subclass off a surrogate class, and write a new surrogate creation function that creates an instance of this new subclass. This more specialized surrogate might do message filtering, caching, monitoring, etc. Call this function after you've performed initialization, but before you do any operations which might create a surrogate of the specified class. It basically overwrites the default surrogate creation function set up by the surrogate stubs. It returns the old surrogate creator function, or `NULL` if was previously no surrogate creator for that class (note: `NULL` return should not really happen unless a mistake or something clever is being done - this means you've added a new node to the surrogate creator function list). iluPFunctionSurrogateCreator is typedeffed as

C++: iluObject* (* iluPFunctionSurrogateCreator ) ( iluKernelObject).

A surrogate creator function should at the minimum create an instance of a surrogate, call the instances member function iluAssociateKernelObject passing the `iluKernelObject,` and then return a pointer to the new instance.

C++: static void iluCppRuntime::iluSetForkProcedure ( iluForkProc pfunction_fork_procedure )

If your using your own threads package call this before calling the ILU kernel functions ilu_SetWaitTech, etc. and pass a pointer to your function that forks a thread. iluForkProc is typedeffed as

C++: iluBoolean (* iluForkProc ) ( void (*pfunction_procedure) (void* pv_argument),

void* pv_argument, ILU_ERRS((no_memory, no_resources, internal)) * p_error )

#### iluCppRuntime - Character Utilities

C++: static iluCardinal iluCppRuntime::iluCharacterStringLength ( const iluCharacter* p_chars )

Returns the length of the `iluCharacter` string

C++: static iluCharacter* iluCppRuntime::iluCharacterStringCopy ( iluCharacter* p_chars_destination, const iluCharacter* p_chars_source )

Copies the source `iluCharacter` string to the destination, returns the destination.

C++: static iluCharacter* iluCppRuntime::iluCharacterStringDuplicate ( const iluCharacter* p_chars_source )

Returns a duplicate of the source `iluCharacter` string

C++: static ILUCPP_BOOL iluCppRuntime::iluCharacterStringEqual ( const iluCharacter* p_chars_one, const iluCharacter* p_chars_two )

Returns true if strings are the same, else false.

C++: static iluCharacter* iluCppRuntime::iluCharStringFromShortCharString ( const iluShortCharacter* pc_shortchars )

Returns a new `iluCharacter` string filled in from the `iluShortCharacter` string.

C++: static ILUCPP_BOOL iluCppRuntime::iluCharStringShortCharStringEqual ( const iluCharacter* pc_chars, const iluShortCharacter* pc_shortchars )

Returns true if the `iluCharacter` string matches the `iluShortCharacter` string.

#### iluCppRuntime - String Binding Handle Utilities

C++: static char* iluCppRuntime::iluFormSBH ( const char* pc_serverid, const char* pc_instance_handle, iluClass the_ilu_class, iluProtocolInfo pc_protocol_type = ((iluProtocolInfo) NULL), iluTransportInfo transport_info = ((iluTransportInfo) NULL) )

C++: static char* iluCppRuntime::iluFormSBHUsingContactInfo ( const char* pc_serverid, const char* pc_instance_handle, iluClass the_ilu_class, const char* p_str_encodedContactInfo = NULL )

Use these to form a string binding handle from relevant parts, if protocol and/or transport info are NULL, current defaults are used. For iluFormSBHUsingContactInfo, p_str_encodedContactInfo is as would be obtained from iluParseSBH.

C++: static ILUCPP_BOOL iluCppRuntime::iluParseSBH ( iluCString str_encodedSBH, iluCString* p_str_plainInstanceHandle = NULL, iluCString* p_str_plainServerID = NULL, iluCString* p_str_plainMstid = NULL, iluCString* p_str_encodedContactInfo = NULL, iluCardinal* p_card_encodedContactInfoLen = NULL, ILUCPP_BOOL* p_b_malloced_contact_info = NULL) )

Parse a string binding handle, returning whichever elements are specified by passing in non-NIL pointers. Caller retains ownership of URL argument. If p_str_plainInstanceHandle != NIL, ownership of *p_str_plainInstanceHandle is passed to caller iff successful. Similarly for p_str_plainServerID and p_str_plainMstid. *p_str_encodedContactInfo is set to point into the given URL (The whole sequence of contact info is returned in *p_str_encodedContactInfo) , and *p_card_encodedContactInfoLen is set to the length of the contact info substring; the next character is left unmolested. If the p_b_malloced_contact_info out parameter is true, then caller must arrange to free it.

#### iluCppRuntime - File Descriptor Budget

C++: static iluCardinal iluCppRuntime::iluGetFDBudget( )

C++: static iluCardinal iluCppRuntime::iluSetFDBudget ( iluCardinal card_size )

Get and set ILU file descriptor budget. iluSetFDBudget returns the new budget. Because ILU may open multiple connections to a server, we need some policy for when to close them. That policy is this: the application gives the ILU kernel a "File Descriptor Budget" (initally 16). The ILU kernel promises to use no more than this many File Descriptors at once.Off the top of this budget we take FDs needed for serving (one per listening socket and one per accept). The remainder is allocated to outgoing connections (over transports that use FDs -- ie, not inmemory). When we want to consume a new FD, and there's no room left in the budget, we go looking for an idle outgoing connection (one with no outstanding calls) to close. All idle outgoing connections are kept in a doubly-linked list, ordered by when the connection went idle (most recently at the front).

#### iluCppRuntime - Memory Management

C++: static void iluCppRuntime::iluFree ( void* pv /* ILUowned */ )

Use this to free things returned by ILU

C++: static void* iluCppRuntime::iluMalloc ( iluCardinal card_size )

You can use this to malloc things from ILU.

### iluServer

`iluServer` provides a the C++ view of a kernel server object. `iluServers` cannot be copied or assigned.

#### iluServer - Setup and Destruction

C++: iluServer::iluServer ( char* pc_server_id = `NULL`, iluObjectTable* p_object_table = `NULL` /* ILUowned */ , char * pc_protocol_type = `NULL`, iluTransportInfo transport_info = `NULL`, iluPassport* p_passport = `NULL` )

Constructor - If no pc_server_id is specified, one is automatically created based on based on time, hostname, and process id. If p_object_table is `NULL`, a default object table implementation is used. A port is created and added to the server using the specified protocol and transport, and becomes the default port of the server. pc_protocol_type and transport_info default to whatever the default protocol and transport are currently set to. Caller owns pc_server_id p_object_table, pc_protocol_type, transport_info, and p_passport. p_passport points to an `iluPassport,` defaulted to `NULL` - this passport containing an ILU GSS identity, which is used as the identity of the principal offering the service, and put into the connection information in the string binding handle of objects on that server.

C++: virtual iluServer::~iluServer ( )

Destructor - basically destroys the kernel server and breaks all associations between kernel objects in this server and their language specific objects. Indirectly also deletes any `iluObjectTable` used with this iluServer.

C++: virtual void iluServer::iluAddPort (char* pc_protocol_type,

iluTransportInfo transport_info, ILUCPP_BOOL b_become_default_port = `ILUCPP_FALSE`, iluPassport* p_passport = `NULL` )

Adds another port to an existing server If b_become_default_port is `ILUCPP_TRUE` the new port will become the default port for this server. p_passport points to an `iluPassport,` defaulted to `NULL`. this passport containing an ILU GSS identity, which is used as the identity of the principal offering the service, and put into the connection information in the string binding handle of objects on that server. Caller owns the arguments.

C++: virtual void iluServer::iluRun ( int* p_i_stop_on_non_zero = `NULL` )

This runs the main, outer loop of an iluServer. It never returns if p_i_stop_on_non_zero isn't supplied, else it returns when *p_i_stop_on_non_zero is non zero. If you're running threaded this routine simply goes into a sleep loop,

#### iluServer - Default Accessors

C++: static char* iluServer::iluGetDefaultProtocol ( )

C++: static void iluServer::iluSetDefaultProtocol( char* pc_new_default_protocol )

Get and set the default protocol used when adding a port on a `iluServer` - initialized to whatever is set to be the default in the kernel (found in ``ILUSRC/runtime/kernel/iluconf.h'` or ``ILUSRC/runtime/kernel/iluwin.h'`) C++: static const iluTransportInfo iluServer::iluGetDefaultTransport ( )

C++: static void iluServer::iluSetDefaultTransport( iluTransportInfo ppc_new_default_transport_info )

Get and set the default transports used when adding a port on a `iluServer` - initialized to whatever is set to be the default in the kernel (found in ``ILUSRC/runtime/kernel/iluconf.h'` or ``ILUSRC/runtime/kernel/iluwin.h'`) Callee owns pc_new_default_transport_info.

C++: {static iluServer@ampnr{}} iluServer::iluGetDefaultServer ( )

Returns the default `iluServer`, creating one if need be.

C++: static iluServer* iluServer::iluSetDefaultServer ( iluServer& new_default_server )

Sets the default `iluServer,` returns old default, which is `NULL` if no default currently is set.

### iluObject

The most base class for all ILU C++ objects. All objects inherit either directly or indirectly from `iluObject`. All non-static member functions are virtual to allow creative overrides (at your own risk of course). `iluObjects` cannot be copied or assigned.

#### iluObject - Creation and Destruction

C++: iluObject::iluObject ( iluClass the_Class, char* pc_instance_handle = `NULL`, iluServer& the_server = iluServer::iluGetDefaultServer(), ILUCPP_BOOL b_within_object_table = ILUCPP_FALSE )

Constructor - This constructor must be called (only) from the constructors for true objects. For example, in an implementation of a foo::bar :

     foo_bar_impl(char* pc_instance_handle, iluServer& r_an_ilu_server, CORBA(Boolean) b_within_object_table = ILUCPP_FALSE :
              iluObject(foo(bar)::m_ILUClassRecord, pc_instance_handle, r_an_ilu_server, b_within_object_table) {}

If no instance handle is specified, then the value of a monotonicaly increasing, `iluServer` specific counter will be used to generate one. If no server is specified, then the default server will be used. (The default server is generated automatically if needed, and has the an id based on time, hostname, and process id.) Caller owns pc_instance_handle. The new object has a reference count of 1. If b_within_object_table is true, then it is assumed the object is being created inside an iluObjectTable's iluObjectOfInstanceHandle function, meaning that the locks on the server should not be modified.

C++: static iluObject* iluObject::iluStringToObject ( char* pc_string_binding_handle )

Given a string binding handle (e.g. as obtained from iluObjectToString) returns an iluObject* for that object, with the reference count incremented.

C++: virtual iluObject::~iluObject ( )

Destructor ensures that this object is completely disassociated from the ILU kernel The most specific destructor of an object should call iluDeactivate on the object to block any further incoming calls, and wait for any ongoing calls to complete. Next it should perform any object specific cleanup. Finally, the destructor in `iluObject` will break the association between the kernel object and this object, allowing the kernel object to be potentially freed.

C++: virtual void iluObject::iluDeactivate ( )

Ensures this object is not available from the outside. This must be the first thing called by the most specific destructor of an object. If if isn't, then the potential exists (in multithread case) for a call to come in for an object that's in the middle of destruction - a bad thing! This function blocks until there are zero ongoing calls.

C++: virtual void iluObject::iluKernelObjectUnlinked ( )

Called by iluUnlinkKernelObject - you can override this virtual function in your objects to do whatever you like when the association between your object and the kernel object is broken - e.g. delete yourself The implementation in `iluObject` deletes this.

#### iluObject - Object Publication

C++: virtual ILUCPP_BOOL iluObject::iluPublish ( )

Publishes binding information for this object in the binding service Has no effect on object reference count.

C++: virtual ILUCPP_BOOL iluObject::iluWithdraw ( )

Removes binding information for this object from the binding service Has no effect on object reference count.

C++: static void* iluObject::iluLookup (char* pc_instance_handle, char* pc_server_id, iluClass the_class )

Used by stubber generated iluLookup functions in derived classes to lookup an object in the binding service based on its instance and server id and class. Increments reference count of object. To Lookup objects of type T, use the T::iluLookup(char* pc_instance_handle, char* pc_server_id; function produced by the stubber. For example:

    mybar_var =  foo(bar)::iluLookup("foo_instance_0", pc_serverid )

#### iluObject - Accessors

C++: virtual iluServer* iluObject::iluGetServer ( )

Returns pointer to the iluServer that this object resides in.

C++: virtual const char* /* ILUowned */ iluObject::iluId ( )

Returns the objects instance id.

C++: virtual const char* /* ILUowned */ iluObject::iluServerId ( )

Returns the id of the objects ILU Server.

#### iluObject - Informational

C++: virtual iluCString iluObject::iluObjectToString ( )

Returns the ILU string binding handle for the object. Caller get ownership of the string

C++: ILUCPP_BOOL iluObject::iluIsCollectibleObject ( )

Returns true if the object is of a collectible class.

C++: virtual iluCString iluObject::iluObjectToIORString ( )

Returns a string which is the object's name and contact information as specified by the CORBA IIOP spec - caller gets ownership of the string. May return NULL if the object is not exported through an `IIOP` ilu_Port. (Available only when `IIOP` support is configured into ILU.)

C++: virtual iluCString iluObject::iluObjectToURLString ( )

Returns a string which is the object's name and contact information as specified by an `HTTP` URL - caller gets ownership of the string. May return NULL if the object is not exported through an `HTTP` ilu_Port (Available only when `HTTP` support is configured into ILU.)

C++: ILUCPP_BOOL iluObject::iluPing()

Returns `ILUCPP_TRUE` if the true object exists, and the process serving it can be contacted, otherwise `ILUCPP_FALSE`.

C++: ILUCPP_BOOL iluObject::_is_equivalent(iluObject* p_obj)

Returns `ILUCPP_TRUE` if the two objects denote the same thing.

C++: ILUCPP_BOOL iluObject::iluInSameServer(iluObject* p_obj)

Returns `ILUCPP_TRUE` if the two objects are in the same ILU server. Used, for example, to determine if objects are SIBLINGS.

C++: virtual const char* /* ILUowned */ iluObject::iluClassName ( )

C++: virtual const char* /* ILUowned */ iluObject::iluClassId ( )

Return the ILU class name and type id - primarily informational use.

#### iluObject - Reference Counting

C++: virtual void iluObject::iluIncrementReferenceCount( )

C++: virtual void iluObject::iluDecrementReferenceCount( )

Reference count operations - when an object is first created, it has a reference count of one. If the reference count ever goes to zero, delete is called on this. CORBA compliant apps (where objects derive from CORBA::Object) should use the duplicate and release functionality defined in the CORBA specification.

C++: virtual iluCardinal iluObject::iluGetReferenceCount( )

Returns what the current reference count is.

C++: static iluObject* _duplicate(iluObject* p_obj)

Increments the reference count on the object and returns it. Returns NULL if passed NULL.

C++: static iluObject* _narrow(iluObject* p_obj)

Effectively casts the object pointer to an iluObject*.

### iluObjectTable

An abstract C++ class for developers to derive from to provide Object Tables. Object tables cannot be copied or assigned. Besides doing whatever application specific things might need to be done in the constructor and destructor, a class derived from `iluObjectTable` must provide the iluObjectOfInstanceHandle virtual member function.

C++: virtual iluObject* iluObjectTable::iluObjectOfInstanceHandle (iluCString pc_instance_handle /* ILUowned */) = 0;

Called by ILU to create and return a new `iluObject`* with the specified instance handle. ILU retains ownership of pc_instance_handle - i.e. copy it if you need want to hang on to it. Note that when in this function, you are 'inside' the object's server - i.e. you hold the locks on the server - this means that when you create the object, you must specify the 3rd argument to the object's constructor (b_within_object_table) as true.

C++: virtual iluServer* iluObjectTable::iluGetServer ();

Returns the pointer to the iluServer this object table is associated with.

C++: virtual iluObjectTable::~iluObjectTable ( )

Do whatever destroying the Object Table needs to do to free up resources, etc. It gets called when the `iluServer` it's associated with it is shut down.

### iluPassport

Encapsulates `ilu_Passport` functionality

C++: iluPassport::iluPassport ( iluIdentityInfo p_identity_info = `NULL` )

Constructor - creates and returns a passport, optionally containing the specified identity.

C++: virtual iluPassport::~iluPassport ( )

Destructor - frees any associated identities in addition to freeing the passport

C++: static iluPassport* iluPassport::iluGetPassport ( )

C++: static iluPassport* iluPassport::iluSetPassport (iluPassport* p_passport )

Get and set the passport being used for outgoing calls - in the multi-threaded case, this is per-thread Set returns the old `iluPassport`. Note that before your thread exits, you should either call iluSetPassport(`NULL`), or delete the `iluPassport` in use (assuming it's only in use for a single thread).

C++: static iluPassport* /* ILUowned */ iluPassport::iluGetCallerPassport( )

Get the passport of the caller.

C++: virtual void iluPassport::iluAddIdentity ( iluIdentityInfo p_identity_info /* ILUowned */ )

Adds identity to Passport. Only one identity of each type is allowed.

C++: virtual iluIdentityInfo /* ILUowned */ iluPassport::iluFindIdentity ( iluIdentityType p_identity_type )

Returns identity of specified type, if present else `NULL`

C++: static iluIdentityInfo iluPassport::iluCopyIdentity ( iluIdentityInfo p_identity_info )

Returns a copy of the passed identity

C++: ilu_Passport /* ILUowned */ iluPassport::iluGetIluPassport ()

Returns the (kernel) ilu_Passport

### iluGSS

Encapsulates GSS functionality - only defined when ILU is configured with secure transport.

C++: static iluIdentityInfo iluGSS::iluAcquireGSSIdentity ( gss_cred_id_t gss_credential )

C++: static ILUCPP_BOOL iluGSS::iluDecodeGSSIdentity ( iluIdentityInfo p_identity_info, gss_name_t* p_name, iluFineTime* p_good_till_time,gss_OID mechanism, ILUCPP_BOOL* p_b_local, iluCardinal* p_card_flags )

p_identity_info - input; retain; info to decode p_name - output; name in identity p_good_till_time - output; good-till mechanism - input; actual mechanism desired; optional p_b_local - if TRUE, local; otherwise remote p_card_flags - connection flags, as in gss_inquire_context

C++: static gss_cred_id_t iluGSS::iluAcquireGSSCredForName ( char* pc_name, iluCardinal card_lifetime, gss_OID mechanism, ILUCPP_BOOL b_accept_only )

C++: static iluCString iluGSS::iluGSSNameToString ( gss_name_t name )

### iluMainLoop

Subclass from the `iluMainLoop` class if you want to have your own version of the main loop. `iluMainLoops` cannot be copied or assigned. A single threaded application should supply all functions. An application making use of ILU's OS multi-threaded operation should not use a different mainloop. If you're using your own thread package, you must supply all functions, and see the comment for iluCppRuntime::iluInitialize

C++: virtual void iluMainLoop::iluRun ( int* p_i_stop_on_non_zero ) = 0;

Runs the main loop until *p_i_stop_on_non_zero is non-zero.

C++: virtual void iluMainLoop::iluExit ( int* p_i_stop_on_non_zero ) = 0;

Causes the main loop to exit

C++: virtual ILUCPP_BOOL iluMainLoop::iluRegisterInputHandler (int i_fd,

void (* pfunction_input_handler )(int i_fd, void* pv_input_handler_arg ), void* pv_input_handler_arg ) = 0;

Input Handlers - When there is input activity on the file descriptor i_fd, the mainloop will call the registered handler procedure pfunction_input_handler, passing it i_fd and pv_input_handler_arg as arguments. Returns `ILUCPP_FALSE` if it can't do it's job due to some resource limitation.

C++: virtual ILUCPP_BOOL iluMainLoop::iluUnregisterInputHandler ( int i_fd,

void (** ppfunction_input_handler )(int i_fd, void* pv_input_handler_arg ), void** ppv_input_handler_arg ) = 0;

Returns `ILUCPP_FALSE` if input on i_fd was being handled, else `ILUCPP_TRUE`. Sets function and arg ptrs to what they were if anything.

C++: virtual ILUCPP_BOOL iluMainLoop::iluRegisterOutputHandler (int i_fd, void (* pfunction_output_handler )(int i_fd, void* pv_output_handler_arg ), void* pv_output_handler_arg ) = 0;

Output Handlers - When it is possible to perform output on the file descriptor i_fd, the mainloop will call the registered handler procedure pfunction_output_handler, passing it i_fd and pv_output_handler_arg as arguments.

C++: virtual ILUCPP_BOOL iluMainLoop::iluUnregisterOutputHandler (int i_fd,

void (** ppfunction_output_handler )(int i_fd, void* pv_output_handler_arg ), void** ppv_output_handler_arg ) = 0;

Returns `ILUCPP_FALSE` if output on i_fd had a handler, else `ILUCPP_TRUE` Sets function and arg ptrs to what they were if anything.

C++: virtual iluAlarm iluMainLoop::iluCreateAlarm ( ) = 0;

Creates an alarm. An alarm is an active object which can be set to asynchronously invoke a procedure with an argument at a specified time. An alarm may be something like a pointer to a structure that has some internal structure, but from the point of view of an alarm user, it's just a handle that is used to specify a particular alarm to be set or cleared.

C++: virtual void iluMainLoop::iluSetAlarm(iluAlarm the_alarm, iluFineTime alarm_time, void (*pfunction_alarm_handler)(void* pv_alarm_handler_arg), void* pv_alarm_handler_arg ) = 0;

Sets up an alarm to call the handler procedure pfunction_alarm_handler, passing it pv_alarm_handler_arg as an argument, when the alarm_time occurs. C++: virtual void iluMainLoop::iluClearAlarm ( iluAlarm the_alarm ) = 0;

Cancels the alarm (effectively sets the alarm time to infinity).

C++: virtual void iluMainLoop::iluDestroyAlarm ( iluAlarm the_alarm ) = 0;

Destroys the alarm (if alarm is set, does not invoke).

C++: static void iluMainLoop::iluSetFineTimeFromNow( ilu_FineTime* p_finetime, ilu_integer i_secs, ilu_cardinal i_msecs )

Utility function to set the pointed to ilu_FineTime to a time i_secs + i_msecs in the future

C++: static void iluMainLoop::iluSetMainLoop ( iluMainLoop* p_mainloop_instance )

C++: static iluMainLoop* iluMainLoop::iluGetMainLoop ( )

Setting the Main Loop to be used - Call iluSetMainLoop set your mainloop as the one for ILU to use. It should called before any ILU initialization.

C++: static iluAlarm iluMainLoop::iluDefaultLoopCreateAlarm ( )

C++: static void iluMainLoop::iluDefaultLoopSetAlarm ( iluAlarm the_alarm, iluFineTime alarm_time, void (* pfunction_alarm_handler )(void* pv_alarm_handler_arg ), void* pv_alarm_handler_arg )

C++: static void iluMainLoop::iluDefaultLoopClearAlarm ( iluAlarm the_alarm )

C++: static void iluMainLoop::iluDefaultLoopDestroyAlarm ( iluAlarm the_alarm )

When you haven't set the main loop (i.e. you're using ILU's default loop), you can call these functions to create, set and unset alarms. (If you set your own main loop, just call its alarm functions.)

## CORBA 2.0 C++ Considerations

### ORB_init

The CORBA `ORB_init` function may be called instead of `iluCppRuntime::iluInitialize` (which `ORB_init` calls internally). The orb identifier passed to `ORB_init` should be `"ilu"`. If the command line argument `-iluthreaded` is present in the command line arguments passed to `ORB_init`, then ILU will be run in threaded mode, otherwise ILU will run single-threaded.

Go to the previous, next section.