Go to the previous, next section.

# Using ILU with Standard C

## C Mapping Introduction

This document is for the C programmer who wishes to use ILU. (By C, we mean the language defined in the ISO/ANSI standard, not `K&R C', or `Portable C'.) The following sections will show how ILU is mapped into C constructs and how both C clients and servers are generated and built.

Using ILU with C is intended to be compatible with the OMG CORBA specification. That is, all of the naming and stub generation comply with the Common Object Request Broker Architecture, revision 2.0. (6)

Note that ILU does not support non-ANSI variants of the C language. In particular, it relies on having prototypes, all C library functions, and the capabilities of the C pre-processor.

When functions are described in this section, they are sometimes accompanied by locking comments, which describe the locking invariants maintained by ILU on a threaded system. See the file ``ILUHOME/include/iluxport.h'` for more information on this locking scheme, and the types of locking comments used.

A number of macros are used in function descriptions, to indicated optional arguments, and ownership of potentially malloc'ed objects. The macro `OPTIONAL(type)` means that the value is either of the type indicated by type, or the value `NULL`. This macro may only be used with pointer types. The macro `RETAIN(type)` indicates, when used on a parameter, that the caller retains ownership of the value, and when used in the result position, that the called function retains ownership of the value. The macro `PASS(type)` indicates, when used on a parameter, that the caller is passing ownership of the storage to the called function, and when used in the result position, that the called function is passing ownership of the called value to the caller. The macro `GLOBAL(type)` means that neither the caller nor the calling function owns the storage.

## The ISL Mapping to C

### Names

In general, ILU constructs C names from ISL names by replacing hyphens with underscores. Type names and class names are prepended with their interface name. For example, for the ISL type `T-1` in interface `I`, the generated name of the C type would be `I_T_1`.

Method name prefixes are specified by CORBA to be `module-name_interface-name`. C function names for ISL methods are composed of the generated class name prepended to the method name. For example, if the interface name is `X` and the class type name is `Y` and the ISL method name is `Z` then the C callable method name will be `X_Y_Z`. ILU C servers for this method must implement a function called `server_X_Y_Z`.

For field names within records and unions, hyphens are replaced with underscores.

### Interface

The ISL `interface` is mapped to a prefix for all generated type names, constant names, and exception names, by replacing all hyphens in the interface name with underscore characters.

### Basic Types

The following basic ISL types have the corresponding mappings in C, as specified by the CORBA 2.0 standard mapping for C:

- ISL `BOOLEAN` maps to C `CORBA_boolean`
- ISL `BYTE` maps to C `CORBA_octet`
- ISL `CHARACTER` maps to C `CORBA_wchar`
- ISL `SHORT CHARACTER` maps to C `CORBA_char`
- ISL `CARDINAL` maps to C `CORBA_unsigned_long`
- ISL `SHORT CARDINAL` maps to C `CORBA_unsigned_short`
- ISL `LONG CARDINAL` maps to C `CORBA_unsigned_long_long`
- ISL `INTEGER` maps to C `CORBA_long`
- ISL `SHORT INTEGER` maps to C `CORBA_short`
- ISL `LONG INTEGER` maps to C `CORBA_long_long`
- ISL `REAL` maps to C `CORBA_double`
- ISL `SHORT REAL` maps to C `CORBA_float`
- ISL `LONG REAL` maps to C `CORBA_long_double`

### Constants

ISL constants are translated to C `const` expressions initialized to the specified value. Constant names are prepended with their interface name, separated from the name of the constant with a hyphen character.

### Strings and Characters

ISL `character` and `short character` types are represented with the ILU types `ilu_character`, which hold values of 16-bit Unicode, and `ilu_shortcharacter`, which hold values of 8-bit ISO Latin-1.

String sequences (`SEQUENCE OF SHORT CHARACTER` or `SEQUENCE OF CHARACTER`) are just arrays of the character codes for the characters, using either Latin-1 codes (for `SEQUENCE OF SHORT CHARACTER`), or ISO 10646 Unicode codes (for `SEQUENCE OF CHARACTER`). These sequences are terminated with a character code of zero. The terminating code is not counted in the length of the sequence.

### Pickles and Typecodes

ILU pickles are mapped to opaque structures of the type `CORBA_any`, as per the CORBA specification for the type `any`. However, in ILU, the fields of the pickle are not directly accessible. Instead, the following utility functions are provided to manipulate pickles:

Function: PASS(CORBA_any *) ILU_C_Any_Create (RETAIN(CORBA_TypeCode) typecode, RETAIN(void *) value, RETAIN(CORBA_Environment *) env)

Locking: n/a

Create a new pickle from a C value and typecode. The return value is heap-allocated.

Function: PASS(CORBA_any *) ILU_C_Any_Init (RETAIN(CORBA_any *) uninitialized-any, RETAIN(CORBA_TypeCode) typecode, RETAIN(void *) value, RETAIN(CORBA_Environment *) env)

Locking: n/a

Given a pointer to an uninitialized ``CORBA_any`` value uninitialized-any, sets the typecode and value of the any to the specified typecode and value.

Function: PASS(CORBA_any *) ILU_C_Any_ResetValue (RETAIN(CORBA_any *) initialized-any, RETAIN(CORBA_TypeCode) typecode, RETAIN(void *) value, RETAIN(CORBA_Environment *) env)

Locking: n/a

Given a pointer to a previously used ``CORBA_any`` value initialized-any, frees the current value and sets the typecode and value of the any to the specified typecode and value.

Function: PASS(void *) ILU_C_Any_Value ({RETAIN(CORBA_any *)} pickle, {RETAIN(CORBA_Environment *)} env)

Locking: n/a

Returns the C value from the pickle. Returns NIL if the type of the value contained in the pickle is not `known' to the ILU C runtime. Relatively expensive, as it involves several malloc's.

Function: CORBA_TypeCode ILU_C_Any_TypeCode ({RETAIN(CORBA_any *)} pickle, {RETAIN(CORBA_Environment *)} env)

Locking: n/a

Retrieve the CORBA typecode of the value in the pickle. Returns NIL if the type of the value in the pickle is not registered with the ILU C runtime.

Function: PASS(CORBA_any *) ILU_C_Any_Duplicate (RETAIN(CORBA_any *) pickle, RETAIN(CORBA_Environment *) env)

Locking: n/a

Make a copy of an existing pickle without `looking inside'. This call will work even with pickle values that are of types not known to the ILU C runtime.

### Constructed Types

#### Enumeration

ISL enumeration types are mapped C enum types, in an exception to the CORBA specification. Each element of the enumeration is named as `<interface>_<element-name>`. The C `enum` type is `typedef`'ed to the specified name for the type. For example, the ISL definition

    INTERFACE Foo;
    ...
    TYPE Color = ENUMERATION Red, Green, Blue END;
    ...

would produce the following C definition:

    typedef enum { Foo_Red, Foo_Green, Foo_Blue } Foo_Color;

#### Array

Arrays are represented as C arrays.

#### Sequence

Sequence type names, as most type definitions, are formed with the interface name and the type name. Sequence instances are represented to the C programmer as a pointer to the sequence descriptor structure. For each sequence type declared in the interface description, a pseudo-object sequence type is defined in C. These sequence types will hold any number of values of type sequence's primary type. For the sequence
`INTERFACE I;`
`TYPE T2 = SEQUENCE OF T1;`
the following functions are defined:

Sequence Method: PASS(I_T2*) I_T2_Create ( OPTIONAL(unsigned long) `length`, OPTIONAL(T1 *) `initial-values` )

This function creates and returns a pointer to a newly allocated instance of T2. If length is specified, but initial-values is not specified, enough space for length values of type T1 is allocated in the sequence. If initial-values is specified, length is assumed to be the number of values pointed to by initial-values, and must be specified. Note that if type T1 is a `character` or `short character` type, a pointer to a NIL-terminated sequence will be returned; otherwise, a normal CORBA sequence structure will be returned by reference.

Sequence Method: CORBA_unsigned_long I_T2_Length ( I_T2 * s )

Returns the length of s.

Sequence Method: void I_T2_Append ( I_T2 * s, T1 value )

Appends value to the end of s. This function will reallocate space and copy, if necessary.

Sequence Method: void I_T2_Push ( I_T2 * s, T1 value )

Pushes value on to the beginning of the sequence. This function will reallocate space and copy, if necessary.

Sequence Method: void I_T2_Pop ( I_T2 * s, T1 * value-ptr )

Removes the first value from the sequence s, and places it in the location pointed to by value-ptr.

Sequence Method: void I_T2_Every ( I_T2 * s, void (*func)(T1, void *), void * data )

Calls the function func on each element of s in sequence, passing data as the second argument to func.

Sequence Method: RETAIN(I_T1*) I_T2_Nth ( I_T2 * `s`, CORBA_unsigned_long `n` )

Returns the address of the nth element of the sequence s. Returns `ILU_NIL` if n is out of range.

Sequence Method: void I_T2_Init ( I_T2 * s, OPTIONAL(CORBA_unsigned_long) length, OPTIONAL(T1 *) initial-values )

This function works like `T2_Create`, except that it takes a the address of an already-existing T2 to initialize. This can be used to initialize instances of T2 that have been stack-allocated.

Sequence Method: void I_T2__Free ( I_T2 * s )

Frees allocated storage used internally by s. Does not free s itself.

String sequences (`SEQUENCE OF SHORT CHARACTER` or `SEQUENCE OF CHARACTER`) are just arrays of the character codes for the characters, using either Latin-1 codes (for `SEQUENCE OF SHORT CHARACTER`), or ISO 10646 Unicode codes (for `SEQUENCE OF CHARACTER`). These sequences are terminated with a character code of zero. The terminating code is not counted in the length of the sequence. All other sequence types have a record structure, mandated by CORBA:

    typedef struct I_T2 {
      unsigned long _maximum;
      unsigned long _length;
      I_T1 *_buffer;
    } I_T2;

The field `_maximum` contains the number of elements pointed to by `_buffer`. The field `_length` indicates the number of valid or useful elements pointed to by `_buffer`.

For example, the ISL specification

    INTERFACE I;

    TYPE iseq = SEQUENCE OF INTEGER;

would have in its C mapping the type

    typedef struct I_iseq {
      unsigned long _maximum;
      unsigned long _length;
      ilu_integer *_buffer;
    } I_iseq;

In a client program, a pointer to this type would be instantiated and initialized by calling the type specific sequence creation function generated for the sequence, e.g.

            ...
        I_O h;
        ILU_C_ENVIRONMENT s;
        I_iseq sq;
            ...
        sq = I_iseq_Create (0, NULL);
        I_iseq_Append (&sq, 4);
            ...

#### Record

Records map directly into corresponding C structures.

#### Union

Because of the somewhat baroque CORBA concept of union types, unions may take one of several forms.

Generally, ILU unions in C consist of a struct with two members: the type discriminator (a member named "`_d`"), and a union (a member named "`_u`") of the possible values. In a simple ISL union that does not name the elements, the union member names are derived from the ISL data types which compose the union. For example, if the ISL type in interface `I` is `TYPE u1 = UNION INTEGER, SHORT REAL END;` the generated C struct would be

    struct _I_u1_union {
            CORBA_short _d;
            union {
                    CORBA_long integer;     /* 0 */
                    CORBA_float shortreal;  /* 1 */
            } _u;
    };
    typedef struct _I_u1_union I_u1;

Note the discriminator `_d` may take on the values of `0`, for the `integer` field, or `1`, for the `shortreal` field.

In more complex union forms, the user may specify the type of the discriminator as well as the member names and which member corresponds to which discriminator value. Consider the following ISL example:

    INTERFACE I;
    TYPE e1 = ENUMERATION red, blue, green, yellow, orange END;
    TYPE u1 = e1 UNION
     a : INTEGER = red, green END,
     b : SHORT REAL = blue END,
     c : REAL = DEFAULT
    END;

The generated union is:

    typedef struct _I_u1_union I_u1;
    typedef enum { I_red = 0, I_blue = 1, I_green = 2, I_yellow = 3, I_orange = 4 } I_e1;
    struct _I_u1_union {
      I_e1 _d;
      union {
        CORBA_long a;       /* I_red, I_green */
        CORBA_float b;      /* I_blue */
        CORBA_double c;     /* DEFAULT */
      } _u;
    };

This example shows that the discriminator type is to be `I_e1` and that the member names are to be `a`, `b`, and `c`. When the discriminator has the value `I_red` or `I_green` the member `a` has a valid value and the type is interpreted to be `CORBA_long`. When the discriminator has the value `I_green` the member `b` has a valid value and the type is interpreted to be `CORBA_float`. If the discriminator has any other value, the member `c` is expected to have a valid value and the type is interpreted to be `CORBA_double`.

Discriminator types may be `INTEGER`, `CARDINAL`, `ENUMERATION`, `SHORT CARDINAL`, or `SHORT INTEGER`. The default for an unspecified discriminator is `SHORT INTEGER`.

#### Optional

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.

### Object Types

#### Surrogate and True Objects

ILU uses an object system embedded into C. The C type of objects in this system is `ILU_C_Object*`; the identifiers `ILU_C_OBJECT` and `CORBA_Object` can also be used for this type. We recommend the use of `ILU_C_OBJECT`, as it is a macro that expands to the identifier for the C object type specified by the version of CORBA being used (currently 2.0).

Since C has no subtyping relationship isomorphic to that of ISL object types, a more liberal approximation is used: all ISL object types map to the same C type, `CORBA_Object`. However, a `typedef` is emitted for each ISL object type, so an object-type-specific C type name may be used to express intent. For conformance with CORBA, the C name for ISL type I.T is `I_T`.

The C mapping of an object type includes a set of generic functions for the methods introduced at that object type. The name of the generic function for the method M introduced at object type I.T is `I_T_M`. This generic function is used to invoke method M on objects of type I.T (naturally including objects that also have types that are subtypes of I.T). The first argument to a generic function is an object instance (`ILU_C_Object *`) that should have type I.T (among possibly others).

An implementation of an ISL object type is commonly referred to as a class. Classes are represented in the ILU C runtime as the C type `ILU_C_Class`. To create an `ILU_C_Class`, the application calls an object-type-specific function that is part of the stubs. The class-creation procedure named `I_T__MakeClass`, which is declared in generated file ``I.h'`, makes a class for objects that implement object type I.T (and thus all its supertypes). This procedure takes as arguments a set of C procedures that are the implementations of the methods of that class, plus a finalization procedure. The finalization procedure is given access to the private data of the object after the object is destroyed.

For each object type I.T, the generated server-side stub module for I creates a default true class, unless the true code has been generated with the `-nodefaulttrueclass` or `-nodefaulttrueclassfor` command-line switches. Linking with this server-side stub requires the application to supply the procedures that implement the methods of this default class. Those procedures are named `server_I_T_M`, for each method M of I.T. A finalization procedure can be associated with the default class by invoking `I_T__SetDefaultClassFinalization`. Implementations of true objects typically just use this default class, since the methods for this class have to be provided in any case. The function `I_T__CreateTrue` will create an true instance using the default true class for the object type I_T. `I_T__CreateTrue` methods take an instance handle, a server on which to maintain the object, and arbitrary user data, and create and return the true instance of the object. An alternate version of `I_T__CreateTrue`, called `I_T__OTCreateTrue`, is provided for use inside the scope of an object table's incarnation procedure. Also, a generic creation procedure, `ILU_C_CreateTrueObject`, is declared in ``iluchdrs.h'` for application use. The default true class can be registered or changed with the function ``I_T__SetDefaultClass``, which returns the previous setting of the default true class.

Surrogate instances generally use another automatically-constructed class, though custom surrogate classes may be registered with the procedure `ILU_C_RegisterCustomSurrogateType`. Surrogate instances are typically either received as reply values from calls or parameters to calls, or reified from one or more strings with a binding procedure. (A binding procedure is a procedure that takes some name for an object instance, and returns the actual instance.) There are a number of binding procedures available. The simple binding interface to C offers the function `ILU_C_LookupObject`, which takes an object ID and a type, and returns the registered object with that ID, if any. The function `CORBA_ORB_string_to_object` will take a URL for an instance, in any of the supported URL forms, and return an `ILU_C_OBJECT` instance. The function `ILU_C_SBHToObject` is similar to `CORBA_ORB_string_to_object`, except that an expected object type may also be specified, to constrain the process. In addition, the ILU-generated stubs will provide a function called `I_T__CreateFromSBH`, which will either find or create an instance of the specified type, with the specified parameters.

In general, for any object type T, the following C functions are defined:

C Procedure Type: ILU_C_FinalizationProc

Locking: caller may have any locks -- this means that this finalization procedure can do almost nothing ILU-related without potentially violating locking constraints

The finalization procedure for a class of objects. It takes a single parameter, the ``void *`` "instance data" pointer provided at the creation of the object being finalized. Ownership of (instanceData) is passed to this procedure. It has a return type of ``void``.

Function: ILU_C_Class T__MakeClass ( method-1-type method-1-proc, ... method-N-type method-N-proc, ILU_C_FinalizationProc _finalize )

Locking: Main Invariant holds

Creates a C class of objects that export object type T (and all its supertypes), given implementations for all the methods of that type. `ILU_C_CreateTrueObject` can then be called to create instances of this class.

Function: ILU_C_Class T__SetDefaultClass ( ILU_C_Class c )

Locking: Main Invariant holds

Sets the default true class of the type T to be c, and returns the previous default true class setting.

Function: void T__SetDefaultClassFinalization ( ILU_C_FinalizationProc f )

Locking: Main Invariant holds

Sets the finalization method of the default class for object type T.

Function: OPTIONAL(T) T__CreateTrue ( OPTIONAL(RETAIN(char *)) instance-id, OPTIONAL(GLOBAL(ilu_Server)) server, OPTIONAL(PASS(void *)) user-data )

Locking: Main Invariant holds

Creates an instance of the default class for type T, exporting it with instance-id instance-id, exporting it via server server, associating the value user-data with it. If instance-id is not specified, a server-relative instance-id will be assigned automatically. If server is not specified, a default server will be created automatically.

Function: OPTIONAL(T) T__OTCreateTrue ( RETAIN(char *) instance-id, GLOBAL(ilu_Server) server, OPTIONAL(PASS(void *)) user-data )

Locking: Inside(server, T)

Similar to `T__CreateTrue()`, but designed to be used within the `ot_object_of_ih` function of an object table (section Servers and Ports). Requires kernel server locks to be held before invocation.

Creates an instance of the default class for type T, exporting it with instance-id instance-id, exporting it via server server, associating the value user-data with it.

Function: OPTIONAL(T) T__CreateFromSBH ( RETAIN(char *) sbh, RETAIN(CORBA_Environment *) Env)

Locking: Main Invariant holds

Finds or creates an instance of T, using the given object reference.

Class Var: extern `ilu_Class` T__MSType

A value, of type `ilu_Class` (which, despite its poorly-chosen name, identifies an object type, not a class), that identifies the object type T.

In the following example, the ILU definition is:

    INTERFACE I;

    TYPE T = OBJECT
      METHODS
        M ( r : REAL ) : INTEGER
      END;

This definition defines an interface `I`, an object type `T`, and a method `M`. The method `M` takes a `REAL` as an argument and returns an `INTEGER` result. The generated C header file would include the following statements:

    typedef ILU_C_OBJECT I_T;

    ILU_C_Class I_T__MakeClass(
      ilu_integer (*I_T_M__Impl)
         (I_T _handle, ilu_real r, ILU_C_ENVIRONMENT *_status),
      ILU_C_FinalizationProc _finalize);

    I_T I_T__CreateFromSBH (char *sbh, ILU_C_ENVIRONMENT *Env);
    I_T I_T__CreateTrue (ilu_string ih, ilu_Server server, void *user_data);
    I_T I_T__OTCreateTrue (ilu_string ih, ilu_Server server, void *user_data);

    ilu_integer I_T_M (I_T, ilu_real, ILU_C_ENVIRONMENT *);

    ilu_integer server_I_T_M (I_T, ilu_real, ILU_C_ENVIRONMENT *);

The functions `I_T__CreateFromSBH`, `I_T__CreateTrue`, and `I_T__OTCreateTrue` are used to create instances of the class `I_T`. `I_T__CreateFromSBH` is used by clients. `I_T__CreateTrue` is used by servers for normal circumstances, and `I_T__OTCreateTrue` is used in object table implementations; both return objects whose `M` method is implemented by `server_I_T_M`. Alternatively, servers and/or object tables could use `I_T__MakeClass` and `ILU_C_CreateTrueObject`. The pointer returned in each case is the object instance and must be passed with each method invocation.

#### Interface Inheritance

Through interface inheritance, an object type may participate in the behaviors of several different types that it inherits from. These types are called ancestors of the object type. In C, an object type supplies all methods either defined directly on that type, or on any of its ancestor types.

Consider the following example:

    INTERFACE I2;

    EXCEPTION E1;

    TYPE T1 = OBJECT
      METHODS
        M1 (a : ilu.CString) : REAL RAISES E1 END
      END;

    TYPE T2 = OBJECT
      METHODS
        M2 ( a : INTEGER, Out b : INTEGER )
      END;

    TYPE T3 = OBJECT SUPERTYPES T1, T2 END
      METHODS
        M3 ( a : INTEGER )
      END;

The object type `T3` inherits from the object types `T1` and `T2`. Thus, eight C procedures are relevant to the interface `I2`: the three generic functions `I2_T1_M1`, `I2_T2_M2`, and `I2_T3_M3`, and the five default method implementations `server_I2_T1_M1`, `server_I2_T2_M2`, `server_I2_T3_M1`, `server_I2_T3_M2`, and `server_I2_T3_M3`. A module that implements true instances of `T3` using the default class would define the last three procedures (the other two default method implementations, for messy reasons described in the next paragraph). A client uses only the three generic functions.

Sadly, the current state of the C-stubber causes an additional complexity for server implementors. ``I2-true.c'` contains the server-side stubs ("skeletons", in OMG parlance) needed in any program that implements any object type that is a subtype of any object type defined in ``I2.isl'`. ``I2-true.c'` also contains the code that creates the default classes for all the object types defined in ``I2.isl'`; this code makes external references to the default implementation procedures, thus requiring any program that links with ``I2-true.o'` to supply those default implementation procedures --- even if those default classes are not used. A simple workaround is to supply dummy procedures to satisfy the linker. The stubs can also be generated with the command-line options `-nodefaulttrueclass` or `-nodefaulttrueclassfor`, which will prevent generation of the code that creates the default true classes. However, if this technique is used, be aware that either a default true class must be registered manually, or true instances must be created with ``ILU_C_CreateTrueObject``.

#### Accessing the String Binding Handle, IOR, or Object ID

Several functions are provided to give access to various identifiers of an instance. The function `ILU_C_SBHOfObject` will return the ILU URL for an instance; the function `ILU_C_IOROfObject` will return the CORBA URL for an object, if support for IIOP is configured into ILU; the function `CORBA_ORB_object_to_string` will return either the IOR, if `IIOP` support has been configured in, or the SBH, if not; the two parts of the object ID, the server id and the instance handle, may be obtained with a call on `ILU_C_IDOfObject`. See the API reference section of this chapter for more information on these functions.

#### Distinguishing Between Local and Remote Instances

It is occasionally useful to distinguish between local and remote instances. There are three cases here: the case where the instance is a true object, the case where the instance is a surrogate for a true instance implemented in another language in the same address space, and the case where the instance is a surrogate for a true instance in a different address space. There is currently no good way to distinguish these cases in the C runtime.

#### Object Implementation

This information is provided for those interested in the implementation of the C object system. It is not guaranteed to remain the same from release to release.

The interface ``ILUSRC/runtime/c/ilucstub.h'` contains the C declarations relevant to the material here.

A C class is represented by a pointer to a struct that holds a finalization procedure and a dispatch table. The dispatch table is an array of sections, one from each object type implemented by the class. Each section is a struct containing the `ilu_Class` (remember, this identifies a type, not a class) that this section is for, and an array of procedure pointers, one per method introduced at that object type.

For each method directly defined in the type, a generic function is defined in the common code for its interface, which dispatches to the appropriate method. It does this by walking down the dispatch table for the object's class, until it finds a section that contains the appropriate `ilu_Class` value (that is, the value of `ilu_Class` that matches the `ilu_Class` at which this method was introduced), then calling the method pointer which is indexed in the section's array of method pointers by the index of the method. The generic functions have the correct type signature for the method. They can be referenced with the `&` operator.

#### Methods

All ISL methods of an object type map to C functions which operate on instances of the C object system as described above. `IN`, `OUT`, and `INOUT` parameters appear in the C function in the same order as they appear in the ISL definition of the function.

`ASYNCHRONOUS` methods have no return values and raise no user-specified exceptions. They may return before the completion of the true method. `FUNCTIONAL` methods are not cached by the C ILU runtime.

In addition to its specified arguments, the methods `I_T_M` and `server_I_T_M` take an instance of the type `I_T` and a reference to a variable of type `ILU_C_ENVIRONMENT *`, which is a macro defined to be the appropriate CORBA environment type, and is used to return exception codes. The environment struct pointed to by the environment argument must be instantiated in a client; its address is passed as the last argument to each method. True procedures must expect a pointer to this structure as the last argument. For instance, the C client calling the method for `M` might be as follows:

    #include "I.h"

    int main (int ac, char **av)
    {
      double atof( );
      I_T inst;
      CORBA_long result;
      CORBA_double f;
      ILU_C_ENVIRONMENT ev;

      I__Initialize( );
      f = atof (av[1]);
      inst = I_T__CreateFromSBH (av[2], &ev);
      if (!ILU_C_SUCCESSFUL(&ev)) {
        printf( "CreateFromSBH raised exception <%s>\n",
          ILU_C_EXCEPTION_ID(&ev));
        return(1);
      }
      result = I_T_M (inst, f, &ev);
      if (!ILU_C_SUCCESSFUL(&ev)) {
        printf( "exception <%s> signalled on call to I_T_M\n",
          ILU_C_EXCEPTION_ID(&ev));
        return(2);
      }
      printf( "result is %d\n", result );
      return(0);
    }

Note the call on the interface-specific client initialization procdedure `I__Initialize`; these are described in a later section.

The string binding handle is obtained from standard input along with some floating-point value. The class specific function `I_T__CreateFromSBH` is then called to obtain the object instance. This function was passed the string binding handle, and a `CORBA_Environment` in which to report exceptions. The returned object instance is then passed as the first argument to the method `I_T_M`, along with the environment `ev`, and the single actual `CORBA_double` argument `f`. `I_T_M` returns an `CORBA_long` value which is placed in `result`.

The true implementation of the method `M` might use the default class, supplying the implementation of the one method as follows:

    ilu_integer server_I_T_M ( I_T h, ilu_real u, ILU_C_ENVIRONMENT *s )
    {
      return( (ilu_integer) (u + 1) );
    }

In this simple example, the corresponding server, or true, method computes some value to be returned. In this case it adds one to its `ilu_real` argument `u`, converts the value to an integer, and returns that value. Note that the server method, if not signalling any exceptions, may ignore the environment parameter.

#### Parameter Passing Considerations

Here is ILU's version of table 20 from the CORBA 2.0 spec. `T` is the C mapping of the type in question. The `Exn` column describes how exception parameters appear in the parameter-conveying member of a status struct.

    DataType        In      InOut   Out        Return    Exn
    --------        --      -----   --        ------    ---
    scalar          T       T*      T*         T         T*
    optional        T       T*      T*         T         T*
    object          T       T*      T*         T         T*
    record, fixed   T*      T*      T*         T         T*
    record, var     T*      T*      T**        T*        T*
    union, fixed    T*      T*      T*         T         T*
    union, var      T*      T*      T**        T*        T*
    string          T       T*      T*         T         T*
    other sequence  T*      T*      T**        T*        T*
    array, fixed    T       T       T          T_slice*  T*
    array, var      T       T       T_slice**  T_slice*  T*

#### Exceptions

C has no defined exception mechanism. As already indicated, exceptions are passed in ILU C by adding to the end of each method an additional status argument that can convey an exception code and a value of a type associated with that exception. To signal an exception, a method implementation sets the exception code and supplies the parameter value (if any).

An exception parameter is conveyed in the status argument as a C pointer; the parameter-conveying member is declared to be a `void *`. In particular, this pointer is a pointer to a value of the type that is the C mapping of the exception's ISL parameter. For an exception that has no parameter, the parameter-conveying member is not meaningful.

In the following example, the `div` method can raise the exception `DivideByZero`:

    INTERFACE calc;

    TYPE numerator = INTEGER;

    EXCEPTION DivideByZero : numerator;

    TYPE self = OBJECT
      METHODS
        Div( v1 : INTEGER, v2 : INTEGER ) : INTEGER RAISES DivideByZero END
      END;

The generated include file ``calc.h'` contains the exception definitions:

    #ifndef __calc_h_
    #define __calc_h_
    /*
    ** this file was automatically generated for C
    ** from the interface spec calc.isl.
    */

    #ifndef __ilu_c_h_
    #include "ilu-c.h"
    #endif

    extern ILU_C_ExceptionCode    _calc__Exception_DivideByZero;
    #define ex_calc_DivideByZero _calc__Exception_DivideByZero

    typedef ilu_integer calc_numerator;
    typedef calc_numerator calc_DivideByZero;

    typedef ILU_C_OBJECT calc_self;

    calc_self calc_self__CreateTrue ( char *id, ilu_Server server,
       void * user_data);
    calc_self calc_self__CreateFromSBH ( char * sbh, ILU_C_ENVIRONMENT *Env );

    ilu_integer calc_self_Div( calc_self, ilu_integer, ilu_integer,
       ILU_C_ENVIRONMENT *Env );

    extern void calc__BindExceptionValue (ILU_C_ENVIRONMENT *, ilu_Exception, ...);

    #endif

The method implementation for `Div` in the true module must detect the divide-by-zero condition and raise the exception:

    long server_calc_self_Div (calc_self h, ilu_integer u, ilu_integer v,
                               ILU_C_ENVIRONMENT *s)
    {
      calc_numerator n = 9;

      if ( v == 0 )
        {
          s->_major = ILU_C_USER_EXCEPTION;
          s->returnCode = ex_calc_DivideByZero;
          s->ptr = (void *) malloc(sizeof(calc_numerator));
          *((calc_numerator *) (s->ptr)) = n;
          s->freeRoutine = (void (*) (void *)) 0;
          return( u );
        }
      else
        return( u / v );
    }

When freeing the parameter requires more than just freeing `s->ptr`, a non-NULL `s->freeRoutine` is provided that does the additional freeing; `s->freeRoutine` is given one argument, `s->ptr`, and returns `void`.

The generated stubs offer as a convenience a variadic procedure (`calc__BindExceptionValue`) that can be used to raise any exception declared in the interface. For an exception that has no parameter, this procedure takes just two actual arguments. For an exception with a parameter, the parameter value is given as the third actual argument, using the usual calling convention for passing `IN` arguments of its type. Using this procedure, the above code would be:

    long server_calc_self_Div (calc_self h, ilu_integer u, ilu_integer v,
                               ILU_C_ENVIRONMENT *s)
    {
      calc_numerator n = 9;

      if ( v == 0 )
        {
          calc__BindExceptionValue(s, ex_calc_DivideByZero, n);
          return( u );
        }
      else
        return( u / v );
    }

The exception is sent back to the client, which can detect it thusly:

      ...
      calc_self instance;
      ILU_C_ENVIRONMENT s;
      ilu_integer i, j;
      ilu_integer val;
      ...
      instance = calc_self__CreateFromSBH (sbh, &s);

      if (! ILU_C_SUCCESSFUL(&s)) {
        fprintf (stderr, "CreateFromSBH(%s) raised %s\n",
          sbh, ILU_C_EXCEPTION_ID (&s) );
        exit(1);
      }

      val = calc_self_Div (instance, i, j, &s);

      /* check to see if an exception occured */

      if (! ILU_C_SUCCESSFUL(&s)) {
        /* report exception to user */
        char *p;

        p = ILU_C_EXCEPTION_ID (&s);

        if (p == ex_calc_DivideByZero) {
          calc_numerator *ip;
          ip = (calc_numerator *) ILU_C_EXCEPTION_VALUE (&s);
          fprintf (stderr, "%s signaled:  numerator = %d\n", p, *ip);
          }
        else {
          /* odd exception at this point */
          fprintf (stderr, "Unexpected <%s> on call to Div.\n", p);
          }
        /* free up any transient exception data */
        ILU_C_EXCEPTION_FREE (&s);
        }
      else {
        /* no exception - print the result */
        printf( "result is %d \n", val );
        }
      ...

For more complex exception types, it is often helpful to define a procedure in C specifically to raise them.

#### Garbage Collection of C Instances

Both true and surrogate instances of `ILU_C_OBJECT` are reference-counted; that is, each instance contains a counter which indicates how many uses are currently being made of that object. When you wish to use an object for another purpose, you should increment the reference count by calling the procedure `CORBA_Object_duplicate`, which will return a copy of the instance that you can use for the new purpose. When you are finished with an instance, you should call `CORBA_Object_release` to release your claim on the object's resources. When the reference count of the object returns to zero, the object is finalized.

For COLLECTIBLE true instances, the ILU kernel will maintain a distributed reference count on the instance automatically. That is, so long as any client of the server has a reference to the object, the true instance will not be finalized.

### Issues in Mapping OMG IDL to C

The ILU system does not support the OMG IDL type `fixed`, which is a representation of binary-coded-decimal, or BCD. We have no immediate plans to support it in the future.

## Access to Standard ILU Features

### Servers and Ports

The C type which represents an ILU kernel server is `ILU_C_Server`. True servers can be created with the function `ILU_C_InitializeServer`.

Instances of `ILU_C_Server` are reference-counted, in the same way that instances of `ILU_C_OBJECT` are. Call `ILU_C_Server_duplicate` and `ILU_C_Server_release` to keep track of your usage of `ILU_C_Server` values. `ILU_C_CloseServer` and its relatives perform functions orthogonal to `ILU_C_Server_release`. The actual server will be destroyed only when there is no reason to maintain it; in addition to the reference counting introduced here, the existence of `ILU_C_OBJECT` values in that server count as another reason to maintain the server.

A kernel server can export itself via multiple ports. `ILU_C_InitializeServer` may create one, and `ILU_C_AddPort` can be called to create more.

#### Object Tables

It is sometimes useful to have a server create true objects only when they are mentioned by a client's actual invocation of a method on them. This is allowed in ILU by an interface called an object table, associated with a server. An object table contains two functions, one of which creates a new true instance when called with an instance handle, and the other of which frees the object table when the server is destroyed. Object tables are associated with servers when the server is created. A value of type `ILU_C_ObjectTable` may be created by a call on `ILU_C_CreateObjectTable`; see the API reference for more information about this function.

#### Server Relocation Functionality in C

The server relocation functionality (see section Server Relocation) is accessed by `ILU_C_SetServerRelocationProc` (see section Server Manipulation).

#### Exception Information Functionality in C

See section Exception Information in C.

### Threading and Event Loops

The ILU C runtime allows the use of several different kernel threads packages, application-specific threads packages, or various kinds of event loops. See section Threads and Event Loops for a general discussion of threads and event loops in ILU.

The two macros `ILU_C_USE_OS_THREADS` and `ILU_C_FINISH_MAIN_THREAD` (see section Server Manipulation) are provided to allow use of standard Win32 threads, POSIX threads, or Solaris threads. Application-specific threads packages can also be used by explicitly setting the wait tech, lock tech, and main loop via calls on the ILU kernel (see @ref{} for more information on these functions), then instructing the C runtime on how to fork a new thread by calling `ILU_C_SetFork`.

If no thread technology is specified, ILU's C runtime will operate in a single-threaded (i.e., event loop) manner, using the default ILU main loop. That main loop can also be replaced with an application-specific event loop system if desired; this is often useful when using a toolkit like Xt or Tk. This replacement works by calling the kernel procedure `ilu_SetMainLoop`. In the case of the C runtime, moreover, several examples of how to set the event loop are provided in the directory ``ILUSRC/runtime/mainloop/'`. They will have been automatically built into a library and installed into ``ILUHOME/lib/'` if configured in during the build process. They are useful examples of how to set the event loop to override the ILU default event loop.

For single-threaded operation, the main loop must be invoked. This can be done with either `ILU_C_Stoppable_Run`, `ILU_C_Run`, `ILU_C_StoppableRun`, or `ILU_C_FINISH_MAIN_THREAD` (see section Server Manipulation -- which is woefully incomplete and out of date).

For multi-threaded operation, no main loop need -- or even really can -- be invoked. Some of the aforementioned "main loop" procedures also "work" in multi-threaded runtimes -- they simply block the calling thread.

### Custom Records

Custom record support in the ILU C runtime provides support for replacing the default generated record type `R` with a different struct type `S`. `S` must have a field of type `R` as its first field.

Custom record support for a particular ISL record type can be specified by calling ``ILU_C_RegisterCustomRecord()`` on the `CORBA_TypeCode` value for the type. Note that this allows you to register a function to be called just before marshalling the value to another address space (among other functions). This `pre-output' function may be called more than once on the same call, if the protocol selected requires sizing of arguments. It should be written so that repeated calls on the same value have no effect.

### Custom Surrogates

Custom surrogates allow the user to specify custom surrogate object types which may have additional functionality in terms of caching or other side effects, and have them created instead of the default ILU surrogate object type when an instance is received. This functionality is provided in the C runtime with the function `ILU_C_RegisterCustomSurrogateType`.

### String Binding Handle Formation

When a client program is making a call on an object which is provided via an object table, it is often convenient to allow the client to form an appropriate string binding handle for the object, then instantiate a surrogate instance from that string binding handle. The function `ILU_C_FormSBH` is provided to aid client programs in forming string binding handles.

### Simple Binding

The ILU C runtime provides the standard interface to ILU's simple binding mechanism. The function `ILU_C_PublishObject` publishes a true instance; `ILU_C_WithdrawObject` allows it to be withdrawn from the registry. The function `ILU_C_LookupObject` finds and returns an instance with the specified object ID.

### Identities and Passports

See `ILU_C_CreatePassport`, `ILU_C_AddIdentity`, and `ILU_C_DestroyPassport` for managing `ilu_Passport`s.

To pass/receive an `ilu_Passport` in a call, the caller calls `ILU_C_SetPassportContext(pp)` to store pp in a special hidden per-thread slot, and `ILU_C_SetPassportContext()` to retrieve it. pp will remain in that slot until another call to `ILU_C_SetPassportContext` overwrites it. The callee calls `ILU_C_CallerIdentity()` in a true method to fetch pp from the slot. If the caller and callee are both written in C, and the true method has been invoked directly from the same thread, the returned value will be whatever passport has been set with `ILU_C_SetPassportContext()`; otherwise it will be the passport passed by the caller.

### Pipelining in C

A pipeline (see section Pipelining) is represented in C by an `ILU_C_Pipeline`, and is created by calling `ILU_C_CreatePipeline`. A pipeline is associated with calls via a special hidden per-thread slot; this slot is accessed with `ILU_C_SetPipelineContext` and `ILU_C_GetPipelineContext`. When the `ILU_C_Pipeline` is no longer needed, the client calls `ILU_C_ReleasePipeline`.

### Call Order Preservation in C

A serializer (see section Call Order Preservation) is represented in C by an `ILU_C_Serializer`, and is created by calling `ILU_C_CreateSerializationContext`. A serializer is associated with calls via a special hidden per-thread slot; this slot is accessed with `ILU_C_SetSerializationContext` and `ILU_C_GetSerializationContext`. When the `ILU_C_Serializer` is no longer needed, the client calls `ILU_C_ReleaseSerializer`.

### Batching in C

A batcher (see section Batching) is represented in C by an `ILU_C_Batcher`, and is created by calling `ILU_C_CreateBatcher`. A batcher is associated with calls via a special hidden per-thread slot; this slot is accessed with `ILU_C_SetBatcherContext` and `ILU_C_GetBatcherContext`. The application can call `_C_PushBatcher` to initiate delivery all of all call messages buffered for a given batcher. When the `ILU_C_Batcher` is no longer needed, the client calls `ILU_C_ReleaseBatcher`.

## Building C/ILU Applications

### Using the ILU C Stubber

To generate C stubs from an ISL file, use the program c-stubber. Four files are generated from the ``.isl'` file:

- ``interface-name.h'` contains the definitions for the types and procedures defined by the interface and used by the generated stubs.
- ``interface-name-common.c'` contains the general code used by both client and server; and
- ``interface-name-surrogate.c'` contains the client-side and general code for the interface; and
- ``interface-name-true.c'` contains the server-side stubs and code for the interface.

Typically, clients of a module never have a need for the ``interface-name-true.c'` file.

    % c-stubber foo.isl
    header file for interface foo to ./foo.h...
    common code for interface foo to ./foo-common.c...
    code for surrogate stubs of interface foo to ./foo-surrogate.c...
    code for true stubs of interface foo to ./foo-true.c...
    %

#### Command-line Options

The program `c-stubber` supports the following options:

- `-I directory` -- add directory to the list of directories to search for interface definition files. Note that the directory must be separated from the `-I` with whitespace, unlike the convention for C compilers.
- `-dir directory` -- put output files in directory. Will attempt to create directory with `"mkdir directory"` if not already present.
- `-true` -- generate true code.
- `-tname filename` -- put true code in file called filename.
- `-common` -- generate common code.
- `-cname filename` -- put common code in file called filename.
- `-surrogate` -- generate surrogate code.
- `-sname filename` -- put surrogate code in file called filename.
- `-headers` -- generate header code.
- `-hname filename` -- put header code in file called filename.
- `-removefirst` -- for generated files, remove file before generating a new version of the file.
- `-nodefaulttrueclass` -- for true code, don't generate the commands which create default true classes for each class in the interface. This avoids pulling in references to possibly unused default true methods.
- `-nodefaulttrueclassfor classname` -- for true code, don't generate the commands which creates a default true class for the class classname. This avoids pulling in references to possibly unused default true methods. classname is specified as `INTERFACENAME.TYPENAME`, using the ISL interface name and type name.
- `-renames filename` -- use the specified renaming file renames-file. See the following section on "Tailoring Identifier Names" for more information on this.

If none of `-true`, `-surrogate`, `-common`, `-headers` is specified, the default action is to produce all of them. However, if any of those switches is explicitly specified, only those specified will be produced.

#### Tailoring Identifier Names

The option `-renames renames-filename` may be used with `c-stubber` to specify particular C names for ISL types.

It is sometimes necessary to have the C names of an ILU interface match some other naming scheme. A mechanism is provided to allow the programmer to specify the names of C language artifacts directly, and thus override the automatic ISL to C name mappings.

To do this, you place a set of synonyms for ISL names in a renames-file, and invoke the `c-stubber` program with the switch `-renames`, specifying the name of the renames-file. The lines in the file are of the form

    construct ISL-name C-name

where construct is one of `method`, `exception`, `type`, `interface`, or `constant`; ISL-name is the name of the construct, expressed either as the simple name, for interface names, the concatenation `interface-name.construct-name` for exceptions, types, and constants, or `interface-name.type-name.method-name` for methods; and C-name is the name the construct should have in the generated C code. For example:

    # change "foo_r1" to plain "R1"
    type foo_r1 r1
    # change name of method "m1" to "method1"
    method foo_o1_m1 method1

Lines beginning with the `sharp' character ``#'` are treated as comment lines, and ignored, in the renames-file.

This feature of the `c-stubber` should be used as little and as carefully as possible, as it can cause confusion for readers of the ISL interface, in trying to follow the C code. It can also create name conflicts between different modules, unless names are carefully chosen.

### Using ILU Modules From C

Before manipulating surrogate objects, a client module must first call a runtime initialization procedure `Foo__Initialize` for each ISL interface Foo that declares object types whose surrogates are to be manipulated. Additionally, server modules must also call server initialization procedures (see previous section). These initialization calls may be made in any order, and each procedure may be called more than once. However, no two calls may be done concurrently (this is an issue only for those using some sort of multi-threading package).

A client of an exported module may obtain an object instance either by calling a method which returns the instance, or by calling `TYPE__CreateFromSBH()` on the string binding handle of an instance. Once the object instance, which is typically a surrogate instance, but may in fact be a true instance, is held by the client, it can be used simply by making method calls on it, as shown above.

### Implementing an ILU Module With C

This section will outline the construction of a true module exported by an address space. For the example, we will demonstrate the calculator interface described above. We will also use the CORBA 2.0 names for standard types and exceptions, to show that it can be done.

First, some runtime initialization of the server stubs must be done. Call `Foo__InitializeServer` for every ISL interface Foo containing an object type implemented by the address space. Due to a misfeature in the current C support, also call `Bar__InitializeServer` for every ISL interface Bar containing an object type that is a supertype of one defined in Foo (if you don't, the server will get a runtime fault -- due to calling through a NULL procedure pointer --- when serving a call on an inherited method); this may cause you to have to supply dummy procedures, as explained in section Interface Inheritance. Also call any client initialization procedures needed (see next section). These server and client initialization calls can be made in any order, and each initialization procedure can be called more than once. However, no two calls may be done concurrently (this is an issue only for those using some sort of multi-threading package).

Then we create an instance of `calc_self`. We then make the string binding handle of the object available by printing it to stdout. Finally the `ILU_C_Run` procedure is called. This procedure listens for connections and dispatches server methods.

The main program for the server is as follows:

    #include "I2.h"

    CORBA_long
      server_calc_self_Div (calc_self h,
                            CORBA_long u,
                            CORBA_long v,
                            CORBA_Environment *s)
    {
      calc_numerator n = 9;

      if ( v == 0 )
        {
          calc__BindExceptionValue(s, ex_calc_DivideByZero, n);
          return( u );
        }
      else
        return( u / v );
    }

    main (int ac, char **av)
    {
      calc_self s;
      char * sbh;
      CORBA_Object the_orb;
      CORBA_Environment ev;

      the_orb = CORBA_ORB_init (&ac, av, "ilu", &ev);
      if (!ILU_C_SUCCESSFUL(&ev)) {
        fprintf (stderr, "Can't initialize ORB; exception <%s>\n", CORBA_exception_id(&ev));
        CORBA_exception_free(&ev);
        exit(1);
      };

      calc__InitializeServer( );

      s = calc_self__CreateTrue (NULL, NULL, NULL);
      if (s == NULL)
        {
          fprintf (stderr, "Unable to create instance of calc_self.\n");
          exit(1);
        }
      else
        {
          sbh = CORBA_ORB_object_to_string (the_orb, s, &ev);
          if (ev._major == CORBA_NO_EXCEPTION)
            {
              printf ("%s\n", sbh);
              ILU_C_Run (); /* enter main loop; hang processing requests */
            }
          else
            {
              fprintf (stderr,
                       "Attempt to obtain sbh of object %p signalled <%s>.\n",
                       s, CORBA_exception_id(&ev));
              CORBA_exception_free(&ev);
              exit(1);
            }
        }
    }

### Libraries and Linking

For clients of an ILU module, it is only necessary to link with the ``interface-name-surrogate.o'` and ``interface-name-common.o'` files generated from the C files generated for the interface or interfaces being used, and with the two libraries ``ILUHOME/lib/libilu-c.a'` and ``ILUHOME/lib/libilu.a'` (in this order, as ``libilu-c.a'` uses functions in ``libilu.a'`).

For implementors of servers, the code for the server-side stubs, in the file ``interface-name-true.o'` compiled from ``interface-name-true.c'`, and in the file ``interface-name-common.o'` compiled from ``interface-name-common.c'`, should be included along with the other files and libraries.

## ILU C API

In addition to the functions defined by the CORBA mapping, the ILU C mapping provides some other functions, chiefly for type manipulation, object manipulation, and server manipulation. There are also a number of macros provided for compatibility with both versions of CORBA (revision 2.0).

### General

Exception: CORBA_string ex_CORBA_InvalidName

Raised by ``CORBA_ORB_resolve_initial_references`` to indicate that no binding for the specified service_name is known. The associated value is the service name. Note that this differs from the strict CORBA definition of this exception, which has no associated value.

Function: CORBA_Object CORBA_ORB_init ( {int *} argc, {char **} argv, CORBA_string orb_id, {CORBA_Environment *} env)

Locking: Main Invariant holds

Called to initialize the ILU runtime, and acquire the "orb" object. The return value of this call is used in subsequent calls to other CORBA utility functions.

If the environment variable `ILU_COS_NAMING_IOR` is bound to a string binding handle for a `CosNaming` service, this call will bind the service name `"NameService"` to the object specified by that string binding handle.

Function: CORBA_ORB_ObjectIdList CORBA_ORB_list_initial_services ( CORBA_Object the_orb, {CORBA_Environment *} env)

Locking: Main Invariant holds

Returns a list of service names which can be usefully used in calls to ``CORBA_ORB_resolve_initial_references()``. The type ``CORBA_ORB_ObjectIdList`` is a normal CORBA sequence of strings.

### Type Manipulation

Function: OPTIONAL(ilu_Class) ILU_C_FindILUClassByTypeName ( RETAIN(ilu_string) type-name )

Locking: L1_sup < otmu, L2, Main unconstrained.

Given the type-name of an ILU object type, of the form `"Interface.Typename"`, returns the `ilu_Class` value for it. This value can be used to compare types for equality.

Function: OPTIONAL(ilu_Class) ILU_C_FindILUClassByTypeID ( RETAIN(ilu_string) type-id)

Locking: L1_sup < otmu; L2, Main unconstrained.

Given the type-id of an ILU object type, of the form `"ilu:gfbSCM7tsK9vVYjKfLole1HOBDc"`, returns the `ilu_Class` value for it. This value can be used to compare types for equality.

Function: GLOBAL(OPTIONAL(ilu_string)) ILU_C_ClassName ( RETAIN(CORBA_Object) )

Locking: unconstrained.

Returns the ILU name for the most specific type of an object instance.

Function: GLOBAL(OPTIONAL(ilu_string)) ILU_C_ClassID ( RETAIN(CORBA_Object) )

Locking: unconstrained.

Returns the ILU type ID for the most specific type of an object instance.

Function: ilu_Class ILU_C_ClassRecordOfInstance (CORBA_Object)

Locking: unconstrained.

Returns the `ilu_Class` value for the most specific type of an object instance.

Function: ILU_C_Class ILU_C_RegisterCustomSurrogateType (ilu_Class kernel-type, ILU_C_Class C-type)

Locking: unconstrained.

This function registers C-type as the kind of class to create an instance of when unmarshalling a surrogate instance of most specific type kernel-type. This should be used in conjunction with the automatically generated function ``ObjectType__MakeClass()`` (to create an instance of `ILU_C_Class`), and the automatically generated constant ``ObjectType__MSType`` (the appropriate value for kernel-type). This functionality can be used to implement application-specific surrogate types with caching and other extensions to the basic ILUmodel. The value returned is the previously registered surrogate class for this type.

Function: void ILU_C_RegisterCustomRecord (CORBA_TypeCode record_type, OPTIONAL(ILU_C_CRCreateFn) cfn, OPTIONAL(ILU_C_CRFreeFn) ffn, OPTIONAL(ILU_C_CRPreOutputFn) preoutfn, OPTIONAL(ILU_C_CRPostOutputFn) postoutfn, OPTIONAL(ILU_C_CRPostInputFn) postinfn, CORBA_Environment * env)

Locking: L1 < otmu

Registers a set of functions to be called for a particular record type record_type. The function cfn should create, initialize, and return a value of the desired type; it is called when the kernel is about to unmarshall a value of the type and needs storage for it. The function freefn should perform any clean-up operations necessary for the desired value; they are called before the standard free functions are called on the standard slots of the record type. The function preoutfn should prepare the value to be marshalled to another address space. It may be called repeatedly before the value is actually marshalled, due to sizing requirements imposed by various RPC protocols. The function postoutfn should perform any necessary cleanup after a value has been marshalled; it is expected that this will typically be a NIL function. The function postinfn should perform any initial setup needed after the standard slots of the value have been unmarshalled. This function may raise `BAD_PARAM` (if the type is not a record type), `NO_MEMORY`, and `INTERNAL`.

### Object Manipulation

Function: ILU_C_Object * ILU_C_CreateTrueObject ( ILU_C_Class c, OPTIONAL(ilu_string) instance_handle, OPTIONAL(ILU_C_Server) server, void * instanceData, ilu_boolean inside_server )

Locking: inside_server ? Inside(server, most specific type implemented by c) : Main Invariant.

Instantiates a true object of class c, in server server. If the instance_handle is `NIL`, one will be invented. If the server is `NIL`, the default server will be used. The instanceData is for the private use of the methods of the class. inside_server is `FALSE` for normal cases, but `TRUE` for use in the implementation of an object table.

Function: (OPTIONAL(ILU_C_Object *)) ILU_C_FindObject ( ilu_string server-id, ilu_string instance-handle )

Locking: Main invariant holds.

Given the server-id and instance-handle of an object, returns the object if it exists in the current address space, or `ILU_NIL` if it doesn't exist. Unlike ``ILU_C_SBHToObject()`` and ``ILU_C_LookupObject()``, this function will not create a surrogate for an instance if does not exist -- but if the server-id indicates a server with an object table, the server may create the object dynamically.

Function: ilu_boolean ILU_C_IDOfObject ( CORBA_Object instance, PASS(char **) server-id, PASS(char **) instance-handle )

Locking: Main invariant holds.

Given an instance, returns the server ID and instance handle of that instance. The strings returned are copies; the user must free them with `ilu_free` when finished with them.

Function: ilu_string ILU_C_SBHOfObject ( CORBA_Object instance )

Locking: Main invariant holds.

Given an instance, returns a reference to that instance. The CORBA-specified routine `CORBA_ORB_object_to_string()` should typically be used instead.

Function: OPTIONAL(CORBA_Object) ILU_C_SBHToObject (char * sbh, ilu_Class static_type, RETAIN(CORBA_Environment *) Env)

Locking: Main invariant holds.

Takes an object reference and returns the object. static_type is a type the caller knows the object to have.

Function: OPTIONAL(PASS(char *)) ILU_C_FormSBH (RETAIN(char *) server-id, RETAIN(char *) instance-handle, ilu_Class most-specific-type, RETAIN(ilu_ProtocolInfo) pinfo, RETAIN(ilu_TransportInfo) tinfo, RETAIN(CORBA_Environment *) Env)

Locking: Main invariant holds.

Takes necessary information about an object reference, and returns a well-formed ILU string binding handle for that information. This SBH can then be used to create a surrogate instance, using ``ILU_C_SBHToObject``.

Function: OPTIONAL(PASS(char*)) ILU_C_PublishObject ( CORBA_Object instance )

Locking: Main invariant holds.

Publishes the OID of the instance in a domain-wide registry. This is an experimental interface, and may change in the future.

Function: ilu_boolean ILU_C_WithdrawObject ( CORBA_Object instance, PASS(char *) proof)

Locking: Main invariant holds.

Removes the OID of the instance from the domain-wide registry. proof is the string returned from the call to `ILU_C_PublishObject()`.

Function: OPTIONAL(GLOBAL(CORBA_Object)) ILU_C_LookupObject ( RETAIN(char *) sid, RETAIN(char *) ih, ilu_Class static-class )

Locking: Main invariant holds.

Using the local registry, find and return the object specified by the given Server ID and server-relative Instance Handle. static_type is one you know the actual object must have; it may also have more refined types. For an already-reified surrogate this procedure will reconsider what contact info to use for reaching the server.

Function: OPTIONAL(GLOBAL(CORBA_Object)) ILU_C_CreateSurrogateObject ( ilu_Class type, RETAIN(char *) ih, ilu_Server server, ILU_C_ENVIRONMENT *env )

Locking: Main invariant holds.

Create a new object instance of the specified type on the specified server, with the specified ih. If unable to create such an object, return `ILU_NIL`, and signal the error in env.

This procedure can be used to create new client-side objects for which no true object yet exists. This is the way a client using a server with an object table causes the server to create new instances `on the fly'. When used in this way, the ih must contain all information necessary to allow the server to create the proper true object, as it is the only information passed to the object table's object creation procedure.

Function: CORBA_Object CORBA_Object_duplicate ( CORBA_Object instance, CORBA_Environment * env)

Locking: Main invariant holds.

Increments the reference count of the instance, and returns the instance.

Function: void CORBA_Object_release ( CORBA_Object instance, CORBA_Environment * env)

Locking: Main invariant holds.

Decrements the reference count of the instance. The instance may be destroyed as a result of this operation.

Function: CORBA_unsigned_long CORBA_Object_hash ( CORBA_Object instance, CORBA_unsigned_long max_value, CORBA_Environment * env)

Locking: Main invariant holds.

Returns a hash value for the instance, less than or equal to max_value. Mandated by the CORBA spec.

Function: CORBA_boolean CORBA_Object_is_equivalent ( CORBA_Object instance1, CORBA_Object instance2, CORBA_Environment * env)

Locking: Main invariant holds.

Returns `ilu_TRUE` if ILU believes the two instances to be the same object, `ilu_FALSE` otherwise. Compares the servers and kernel objects of the two instances.

Function: void ILU_C_PingObject ( ILU_C_Object instance, ILU_C_ENVIRONMENT * env)

Locking: Main invariant holds.

Attempts round-trip effectless call on object. May raise system exception to indicate failure.

Function: CORBA_boolean CORBA_Object_non_existent ( CORBA_Object instance, CORBA_Environment * env)

Locking: Main invariant holds.

Returns `ilu_TRUE` if object cannot be successfully pinged. May cause instance to be destroyed.

Function: CORBA_boolean CORBA_Object_is_a ( CORBA_Object instance, CORBA_string repository_id, CORBA_Environment * env )

Locking: Main invariant holds.

Returns `ilu_TRUE` if the instance supports the interface identified by repository_id. May involve a network round trip.

Function: CORBA_boolean CORBA_Object_is_nil ( CORBA_Object instance, CORBA_Environment * env )

Locking: Main invariant holds.

Returns `ilu_TRUE` if the instance is the `NIL` object reference.

Function: CORBA_string CORBA_ORB_object_to_string ( CORBA_Object the_orb, CORBA_Object instance, CORBA_Environment * env )

Locking: Main invariant holds.

Returns a string binding handle for the instance. The argument the_orb is the result of a call to ``CORBA_ORB_init()``.

Function: CORBA_Object CORBA_ORB_string_to_object ( CORBA_Object the_orb, CORBA_String string_binding_handle, CORBA_Environment * env )

Locking: Main invariant holds.

Returns a ``CORBA_Object`` instance for the specified string_binding_handle. The argument the_orb is the result of a call to ``CORBA_ORB_init()``.

Function: OPTIONAL(CORBA_Object) CORBA_ORB_resolve_initial_references ( CORBA_Object the_orb, CORBA_String service_name, CORBA_Environment * env )

Locking: Main invariant holds.

Returns an instance for the service named by service_name, if the system knows of one. The argument the_orb is the result of a call to ``CORBA_ORB_init()``. Raises `ex_CORBA_InvalidName` if the service_name doesn't name a known service.

Function: ilu_integer ILU_C_SetObjectGCTimeout ( {ILU_C_Object *} the_obj, ilu_integer timeout, {ILU_C_ENVIRONMENT *} env)

Locking: Main invariant holds.

Sets the GC timeout of the_obj to timeout. Returns the previous timeout when successful. The GC timeout of an instance is the amount of time ILU will wait before collecting an object without references. This timeout accommodates references to the object that are in transit on the network, and its value should be related to typical maximum network delays on the network being used. Setting the timeout to a value less than the network delay may result in objects being prematurely collected.

### Identity Functions

Function: ilu_Passport ILU_C_CreatePassport (OPTIONAL(PASS(ilu_IdentityInfo)) info, ILU_ERRS((no_memory)) *err)

Create and return a new passport object. If an identity info is passed in, will put that identity in the new passport.

Function: ilu_IdentityInfo ILU_C_CopyIdentity (RETAIN(ilu_IdentityInfo) `info`, ILU_ERRS((no_memory)) *`err`)

Creates and returns a copy of the identity in info.

Function: ilu_boolean ILU_C_AddIdentity (RETAIN(ilu_Passport) `pp`, PASS(ilu_IdentityInfo) `info`, ILU_ERRS((no_memory)) *`err`)

Adds the specified identity to the specified passport, which now owns the identity storage.

Function: OPTIONAL(RETAIN(ilu_IdentityInfo)) ILU_C_FindIdentity (RETAIN(ilu_Passport) `pp`, RETAIN(ilu_IdentityType) `ident_type`)

If the passport pp contains an identity of the specified type, returns a pointer to it, otherwise returns `ILU_NIL`. The passport retains ownership of the identities storage; the caller may make a copy of the identity by calling ``ILU_C_CopyIdentity``.

Several identity types are pre-defined. The identity type `ilu_ConnectionIdentity` is always defined; it consists of a string which describes the connection used by the caller to communicate with the server in a colloquial fashion. The identity type `ilu_SunRPCAuthUnixIdentity` is defined if the `Sun RPC` protocol has been configured in; it provides a struct containing the various pieces of information specified by the protocol specification. The identity type `ilu_GSSIdentity` is available if support for the secure transport has been configured in; it supports a variety of identity schemes under the GSS umbrella. See section Security and the file ``ILUSRC/runtime/kernel/iluxport.h'` for more information on identities and identity schemes.

Function: ilu_cardinal ILU_C_DisplayIdentity ( RETAIN(ilu_IdentityInfo) identity, RETAIN(char *) buf, ilu_cardinal bufsize, {ILU_C_ENVIRONMENT *} env)

Formats a textual display of the identity into buf, respecting bufsize. Returns the actual length of the string (the amount of the buffer that was actually used). May raise an exception through env.

Function: ilu_boolean ILU_C_DecodeGSSIdentity ( RETAIN(ilu_IdentityInfo) identity, OPTIONAL(gss_name_t *) name, OPTIONAL(ilu_FineTime *) good_till, OPTIONAL(gss_OID) mech, OPTIONAL(ilu_boolean) localp, OPTIONAL(OM_uint32 *) flags, {ILU_C_ENVIRONMENT *} env)

Only available if ILU has been configured with support for the GSS security transport. Returns various aspects of the GSS identity in the output parameters name, good_till, mech, localp, and flags. If no return value is specified for an output parameter, that output parameter is not returned. May raise an exception through env, in which case the return value is `ilu_FALSE`. If no exception is signalled, the return value is `ilu_TRUE`.

The meaning of the output parameters are as follows:

- name -- the name of the principal in the identity.
- good_till -- the time when the identity expires.
- mech -- the specific security mechanism used to authenticate the identity. GSS is an `umbrella' system which allows many different security mechanisms to be used through a standard interface.
- localp -- `ilu_TRUE` if the identity is local, `ilu_FALSE` if the identity has been established for a remote principal.
- flags -- this parameter is only valid for remote identities (localp => `ilu_FALSE`). These are the context flags returned from ``gss_inquire_context`` in the ctx_flags parameter. See ``ILUSRC/GSS/doc/draft-ietf-cat-gssv2-cbind-01.txt'` for a complete description.

See ``ILUSRC/GSS/kernel/gssapi.h'` for a definition of the GSS types `gss_name_t`, `gss_OID`, and `OM_uint32`.

Function: OPTIONAL(PASS(ilu_string)) ILU_C_GSSNameToString ( RETAIN(gss_name_t) gss_name, {ILU_C_ENVIRONMENT *} env)

Returns a newly-malloced string containing a textual representation of the principal name in gss_name. May raise an exception through env, in which case returns `ILU_NIL`.

See ``ILUSRC/GSS/kernel/gssapi.h'` for a definition of the GSS type `gss_name_t`.

Function: ilu_IdentityInfo ILU_C_AcquireGSSIdentity (gss_cred_id_t c, {ILU_C_ENVIRONMENT *} err)

Available only if the security transport filter has been configured in. Returns an `ilu_IdentityInfo` corresponding to the given GSS credentials. May raise an exception through err, in which case returns `ILU_NIL`.

See ``ILUSRC/GSS/kernel/gssapi.h'` for a definition of the GSS type `gss_cred_id_t`.

Function: OPTIONAL(gss_cred_id_t) ILU_C_AcquireGSSCredForName (char *name, ilu_cardinal lifetime, gss_OID secmech, ilu_boolean accept_only, {ILU_C_ENVIRONMENT *} err)

Available only if the security transport filter has been configured in. Returns GSS credentials given the cannonical inputs, which are

- name -- specifies the name of the principal to acquire credentials for. It should be of the form `<namespace-identifier>:<principal-name>`, where the namespace-identifier is a stringified `gss_OID`, and the principal-name is a name in that namespace's string formulation. An example would be `"1.2.840.113550.9.1.4:someone@parc.xerox.com"`. The namespace-identifier identifies the iso.member-body.US.Xerox.ILU.GSS.rfc822-namespace namespace, which supports RFC 822 style mail addresses for principal names. See section Security for a discussion of available namespaces.
- lifetime -- specifies the time in seconds that these credentials should be good for. The value `GSS_C_INDEFINITE` may be specified for an infinite period.
- sechmech -- a GSS OID specifying the particular security mechanism which should be used to validate the identity. See section Security for a discussion of available security mechanisms.
- accept_only -- specifies whether the credentials may be used to accept security contexts or initiate them. When specified as `ilu_TRUE`, the returned credentials may only be used to accept security contexts. When specified as `ilu_FALSE`, they may only be used to initiate security contexts.

May raise an exception through err, in which case a value of `ILU_NIL` is returned.

See ``ILUSRC/GSS/kernel/gssapi.h'` for a definition of the GSS types `gss_OID` and `gss_cred_id_t`.

Function: ilu_IdentityInfo ILU_C_AcquireSunRPCAuthUnixIdentity (ilu_string hostname, ilu_shortcardinal uid, ilu_shortcardinal gid, ilu_shortcardinal ngroups, ilu_shortcardinal* groups, ILU_C_ENVIRONMENT * env)

Available only if SunRPC UNIX Authorization has been configured in. Returns an `ilu_IdentityInfo` corresponding to the given UNIX credentials.

Function: ilu_boolean ILU_C_SetPassportContext (ilu_Passport pp)

Sets the special hidden per-thread slot for passports to contain pp. The slot retains that value until explicitly changed later.

Function: ilu_Passport ILU_C_GetPassportContext (void)

Returns the value in the special hidden per-thread slot for `ilu_Passport`s.

Function: ilu_boolean ILU_C_DestroyPassport (PASS(ilu_Passport) pp, ilu_Error * err)

Deallocates the storage associated with the passport, and any associated identities.

Function: OPTIONAL(ilu_Passport) ILU_C_CallerIdentity (void)

Returns the passport associated with the caller, or possibly `ILU_NIL` if being invoked directly in a thread with no passport set. This procedure should only be invoked inside the scope of a true method.

### Call Management Functions in C

Function: ILU_C_Serializer ILU_C_CreateSerializationContext (ILU_C_Server S, ILU_C_ENVIRONMENT *env)

Creates a new instance of the serialization guarantee; this instance is applicable only to calls on objects of S.

Function: ilu_boolean ILU_C_ReleaseSerializer (ILU_C_Serializer si, ILU_C_ENVIRONMENT *env)

A client calls this after it is done using the given `ilu_Serializer`.

Function: ilu_boolean ILU_C_SetSerializationContext (ILU_C_Serializer x)

Sets the special hidden per-thread slot for `ILU_C_Serializer`s to contain x. The slot retains that value until explicitly changed later.

Function: ILU_C_Serializer ILU_C_GetSerializationContext (void)

Returns the value in the special hidden per-thread slot for `ILU_C_Serializer`s.

Function: ILU_C_Batcher ILU_C_CreateBatcher (ilu_FineTime timeout, ilu_boolean pushable, ILU_C_ENVIRONMENT *env)

Creates a new batcher.

Function: ilu_boolean ILU_C_ReleaseBatcher (ILU_C_Batcher val, ILU_C_ENVIRONMENT *env)

A client calls this after it is done using the given `ILU_C_Batcher`.

Function: ilu_boolean ILU_C_SetBatcherContext (ILU_C_Batcher x)

Sets the special hidden per-thread slot for `ILU_C_Batcher`s to contain x. The slot retains that value until explicitly changed later.

Function: ILU_C_Batcher ILU_C_GetBatcherContext (void)

Returns the value in the special hidden per-thread slot for `ILU_C_Batcher`s.

Function: ilu_boolean ILU_C_PushBatcher (ILU_C_Batcher b, ILU_C_ENVIRONMENT * env)

Initiates delivery of all buffered call messages associated with b.

Function: ILU_C_Pipeline ILU_C_CreatePipeline (ILU_C_ENVIRONMENT *env)

Creates a new pipeline.

Function: ilu_boolean ILU_C_ReleasePipeline (ILU_C_Pipeline pl, ILU_C_ENVIRONMENT *env)

A client calls this after it is done using the given `ILU_C_Pipeline`.

Function: ilu_boolean ILU_C_SetPipelineContext (ILU_C_Pipeline x)

Sets the special hidden per-thread slot for `ILU_C_Pipeline`s to contain x. The slot retains that value until explicitly changed later.

Function: ILU_C_Pipeline ILU_C_GetPipelineContext (void)

Returns the value in the special hidden per-thread slot for `ILU_C_Pipeline`s.

### Exception Information in C

Function: GLOBAL(const char *) ILU_C_SysExnMinorDescr ( CORBA_Environment * Env )

Locking: Main Invariant holds.

If Env indicates a system exception has been raised, and the system exception's minor code is ILU-specific, returns a string that describes the minor code. Otherwise returns nil.

Function: GLOBAL(const char *) ILU_C_Exception_SrcFile ( CORBA_Environment * Env )

Locking: Main Invariant holds.

If Env indicates a system exception has been raised, and it was raised locally in the ILU runtime support, returns the name of the source file in which the raise statically occurs. Otherwise returns nil.

Function: int ILU_C_Exception_SrcLine ( CORBA_Environment * Env )

Locking: Main Invariant holds.

If Env indicates a system exception has been raised, and it was raised locally in the ILU runtime support, returns the line number where the raise statically occurs. Otherwise returns 0.

### Server Manipulation

Macro Function: ilu_boolean ILU_C_USE_OS_THREADS

Locking: Main invariant holds.

This macro expands to a function call. If ILU has been configured with os-level thread support, calling this routine will `turn on' that thread support for use with C. This means that a new thread will be forked to handle each incoming connection, in servers, and if the wire protocol being used permits it, a thread will be forked to handle each incoming request. This routine returns FALSE, and emits an error message, if something goes wrong with enabling thread support. It must be called before making any other ILU calls, and before initializing any interfaces via calls to `interface__Initialize` or `interface__InitializeServer`.

Macro Function: void ILU_C_FINISH_MAIN_THREAD ( int returnvalue )

Locking: Main invariant holds.

This routine will return from the `main' thread with the specified value. In some thread systems, the program will be terminated when the main thread returns from `main()`, regardless of whether other threads are running. For these thread systems, this call will simply cause the main thread to idle forever, instead of returning.

Function: void ILU_C_Run (void)

Locking: Main invariant holds.

Called to animate a server and/or other parts of the program. Used only in single-threaded mode. Invokes the event handling loop. Never returns.

Function: OPTIONAL(ILU_C_Server) ILU_C_FullInitializeServer (OPTIONAL(RETAIN(char *)) serverID, OPTIONAL(GLOBAL(ILU_C_ObjectTable)) obj_tab, OPTIONAL(RETAIN(ilu_ProtocolInfo)) protocol, OPTIONAL(RETAIN(ilu_TransportInfo)) transport, OPTIONAL(RETAIN(ilu_Passport)) identity, ilu_boolean createPortAnyway, ilu_boolean port_public)

Locking: Main invariant holds.

Creates and returns an `ilu_Server` with ID serverID, object mapping table obj_tab, using protocol protocol over a transport stack specified by transport. If serverID is specified as `NULL`, a unique string is generated automatically for the server ID. If obj_tab is specified as `NULL`, the default hash table object table is used.

If either protocol or transport is specified, or if createPortAnyway, an `ilu_Port` will automatically be created and added to the `ilu_Server`. protocol, if not `NULL`, is a string that specifies which RPC protocol to use on the port; `NULL` causes use of the default protocol. transport, if not `NULL`, is a sequence of strings that specifies the transport stack to use below the RPC protocol; `NULL` signifies use of the default transport to/from one of the IP addresses of this host. See section Protocols and Transports for details on protocols and transports. If an identity is specified, it may be used for communications security purposes. If an `ilu_Port` is called for, it will become the default port of the `ilu_Server`, and will be public iff requested.

Function: ilu_boolean ILU_C_FullAddPort (ILU_C_Server server, OPTIONAL(RETAIN(ilu_ProtocolInfo)) protocol, OPTIONAL(RETAIN(ilu_TransportInfo)) transport, OPTIONAL(RETAIN(ilu_Passport)) identity, ilu_boolean makeDefault, ilu_boolean port_public, ILU_C_ENVIRONMENT * env)

Locking: Main invariant holds.

Creates a new `ilu_Port` for the server. protocol, transport, identity, and port_public parameterize the `ilu_Port` as for `ILU_C_InitializeServer`.

Function: ilu_boolean ILU_C_AddCInfo (ILU_C_Server server, OPTIONAL(RETAIN(ilu_ProtocolInfo)) protocol, OPTIONAL(RETAIN(ilu_TransportInfo)) transport, ILU_C_ENVIRONMENT * env)

Locking: Main invariant holds.

Adds the given contact info to the given kernel server; used for contact info for ports on other kernel servers of the same server.

Function: ilu_boolean ILU_C_Server_CInfo (ILU_C_Server server, ilu_boolean want_public, char ** protocol, ilu_TransportInfo * transport, ILU_C_ENVIRONMENT * env)

Locking: Main invariant holds.

Obtains the first (if any) public or private (as requsted) contact info sequence of the given server. Caller owns storage pointed to by protocol and transport. On success: callee returns TRUE; callee allocates new storage for string and `ilu_TransportInfo` and returns ownership to caller by storing pointers through protocol and transport. On failure: callee returns FALSE.

Function: (RETAIN(ilu_string)) ILU_C_IDOfServer ( ILU_C_Server server )

Locking: Main invariant holds.

Returns a pointer to the server id of the specified server.

Function: ILU_C_ObjectTable ILU_C_CreateObjectTable (CORBA_Object (*object_of_ih)(ilu_string instance-handle, ilu_private user-data), void (*free_user_data)(ilu_private user-data), ilu_private user-data )

Locking: Main invariant holds.
Locking for object_of_ih: L1 >= {server}, L1 >= {gcmu} if result is true and collectible; L2, Main unconstrained.
Locking for free_user_data: L1 >= {server}; L2, Main unconstrained.

Creates and returns a value of type `ILU_C_ObjectTable` encapsulating the two procedures object_of_ih and free_user_data, and the user-specified data element user-data. When object_of_ih is called, it should create an appropriate `CORBA_Object` with the specified instance handle, and return it. When free_user_data is called, it indicates the end of the object table, and free_user_data should free up any storage associated with user-data.

An object table is associated with a kernel server by passing the object table as a parameter to the function `ILU_C_InitializeServer`. A single object table may be used with multiple different `ilu_Server` instances.

C Procedure Type: ILU_C_ServerRelocateProc

Locking: L1 >= {ilu_Server}; L2 unconstrained

    typedef ilu_boolean
      (*ILU_C_ServerRelocateProc) (ILU_C_Server server,
    			       ilu_private argument,
    			       OPTIONAL(ilu_ProtocolInfo *) new_pinfo,
    			       OPTIONAL(ilu_TransportInfo *) new_tinfo);

This function should return TRUE if new pinfo and tinfo have been stored into the out parameters; otherwise it should return FALSE. It has no mechanism for signalling errors. It is called by a protocol implementation to see if the server wants the caller to be redirected to another location or cinfo stack.

Function: OPTIONAL(void *) ILU_C_SetServerRelocationProc (ILU_C_Server server, ILU_C_ServerRelocateProc relocation_fn, {void *} relocation_arg, ILU_C_ENVIRONMENT * metavar{env})

Locking: Main invariant holds

Ensures that the function relocation_fn will be called with relocation_arg as an argument whenever a request comes in for an object maintained by server, on any connection which uses a relocating protocol (currently only `w3ng` is a relocating protocol). See the definition of ``ILU_C_ServerRelocateProc`` for a description of how it is used. The returned value is the previous value of relocation_arg, if any.

Function: ilu_cardinal ilu_tcp_SetDefaultBuffersize (ilu_cardinal new-buffer-size)

Locking: Main invariant holds.

Sets the default buffersize, in bytes, for TCP transports to new-buffer-size. This default can be overridded by explicitly specifying a buffersize in the tinfo for the port or object. Returns the previous default value. This function is only available if ILU has been configured with support for the TCP/IP transport.

Function: void ilu_tcp_GetStats ( ilu_cardinal * bytes-sent, ilu_cardinal * bytes-read, ilu_cardinal * moorings-created, ilu_cardinal * connections-accepted, ilu_cardinal * connections-opened, ilu_cardinal * currently-open-connections, ilu_cardinal * max-simultaneously-open-connections )

Locking: Main invariant holds.

Returns various statistics about the TCP/IP tranports use of various resources for this process. The values returned are the values since the process was started, or since the reset function ``ilu_tcp_InitializeStats()`` was last called, except for currently-open-connections, which is unaffected by the reset function. This function is only available if ILU has been configured with support for the TCP/IP transport.

Function: void ilu_tcp_InitializeStats ()

Locking: Main invariant holds.

Resets the statistics counters for this process. This function is only available if ILU has been configured with support for the TCP/IP transport.

Function: ilu_FineTime ILU_C_SetDefaultGCPingPeriod ( ilu_FineTime new_period, {ILU_C_ENVIRONMENT *} env)

Locking: L1 < gcmu

The ILU distributed garbage collection protocol detects defunct clients by periodically pinging their GC callback objects. If a client's callback object cannot be successfully pinged, it is removed from the list of clients which have references to any objects on the server. This call sets the ping period to new_period. Only GC callback objects registered after this call will use the new period. Returns the previous ping period upon success.

### CORBA Compatibility Macros

ILU supports CORBA 2.0, and formerly supported either 1.1 or 1.2, depending on how it was installed at your site. A number of macros are defined to make programs less dependent on which version they use.

Macro: ILU_C_OBJECT

Expands to `CORBA_Object`.

Macro: ILU_C_ENVIRONMENT

Expands to `CORBA_Environment`.

Macro: ILU_C_NO_EXCEPTION

Expands to `CORBA_NO_EXCEPTION`.

Macro: ILU_C_USER_EXCEPTION

Expands to `CORBA_USER_EXCEPTION`.

Macro: ILU_C_SYSTEM_EXCEPTION

Expands to `CORBA_SYSTEM_EXCEPTION`.

Macro: ILU_C_SUCCESSFUL ( ILU_C_ENVIRONMENT * ev )

Evaluates to true if no exception has been raised.

Macro: ILU_C_SET_SUCCESSFUL ( ILU_C_ENVIRONMENT * ev )

Sets ev to a successful result.

Macro: ILU_C_EXCEPTION_ID ( ILU_C_ENVIRONMENT * ev )

Returns the `char *` value that is the exception's ID.

Macro: ILU_C_EXCEPTION_VALUE ( ILU_C_ENVIRONMENT * ev )

Expands to `CORBA_exception_value(ev)`.

Macro: ILU_C_EXCEPTION_FREE ( ILU_C_ENVIRONMENT * ev )

Expands to `CORBA_exception_free(ev)`.

Go to the previous, next section.