Go to the previous, next section.
Using ILU with ANSI 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, either revision 1.1 or 1.2, defaulting to 1.2. (8)
Note that ILU does not support non-ANSI variants of the C language. In particular, it relies on having prototypes, all ANSI C library functions, and the capabilities of the ANSI 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 `ILUSRC/runtime/kernel/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-name)
means that the value
is either of the type indicated by type-name, or the value NULL
. This macro
may only be used with pointer values. The macro RETAIN(type-name)
indicates, when used on a parameter type, that the caller retains ownership of the value,
and when used on a return type, that the called function retains ownership of the
value. The macro PASS(type-name)
indicates, when used on a parameter type,
that the caller is passing ownership of the storage to the called function, and when
used on a return type, that the called function is passing ownership of the called
value to the caller. The macro GLOBAL(type-name)
means that neither
the caller nor the calling function owns the storage.
In general, ILU constructs ANSI 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 ANSI C type would be I_T_1
.
Enumeration value names are formed by prepending the interface
name and "_" to the ISL enumeration value name.
Enumeration names and values are then cast into ANSI C
enum
statements.
Constant names are prepended with their interface name. They are
implemented with the const
declaration statements.
Method name prefixes are specified by CORBA to be
module-name_interface-name
.
ANSI 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
ANSI C callable method name will be X_Y_Z
.
ILU ANSI C servers for this method must implement a function called server_X_Y_Z
.
For field names within records, hyphens are replaced with underscores.
Generally, ILU unions in ANSI C consist of a record with two fields: the type discriminator,
a field called "_d",
and a union of the possible values. Since ILU does not
name the fields of a union, the union field names are derived from the
ILU data types which compose the union. For example, if the
ILU type in interface I
is TYPE u1 = UNION INTEGER, SHORT REAL END;
the generated ANSI C struct would be
typedef struct _I_u1_union I_u1; enum I_u1_allowableTypes { I_u1_integer, I_u1_shortreal }; struct _I_u1_union { enum I_u1_allowableTypes _d; union { ilu_integer integer; ilu_shortreal shortreal; } _u; };
Note the discriminator _d
may take on the values of I_u1_integer
or u_u1_shortreal
indicating how to interpret the data in the union.
Also note how the enumerated names are formed: with the interface name
and the type name prepended to the enumeration element name.
In more complex union forms, the user may specify the type of the discriminator as well as the field names and which field 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 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 { ilu_integer a; ilu_shortreal b; ilu_real c; } _u; };
This example shows that the discriminator type is to be I_e1
and that
the field names are to be a
, b
, and c
. When the discriminator
has the value I_red
or I_green
the field a
has a valid value
and the type is interpreted to be integer. When the discriminator has
the value I_green
the field b
has a valid value and the type is
interpreted to be shortreal. If the discriminator has any other value,
the field c
is expected to have a valid value and the type is interpreted
to be ilu_real (double).
Discriminator types may be INTEGER
, ENUMERATION
, or SHORT INTEGER
.
The default for an unspecified discriminator is SHORT INTEGER
.
SHORT REAL
primitive type maps to the
ANSI C float
data type while REAL
maps to double
. The ISL LONG REAL
primitive type currently doesn't map to anything real.
INTERFACE I;
TYPE T2 = SEQUENCE OF T1;
[ANSI C]: I_T2* I_T2_Create ( OPTIONAL(unsigned long) length, OPTIONAL(T1 *) initial-values )
This function creates and returns a pointer to an 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.
[ANSI C]: void I_T2_Append ( I_T2 * s, T1 value )
Appends value to the end of s.
[ANSI C]: void I_T2_Push ( I_T2 * s, T1 value )
Pushes value on to the beginning of the sequence.
[ANSI C]: 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.
[ANSI C]: 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.
[ANSI C]: void I_T2_Init ( I_T2 * s, OPTIONAL(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.
[ANSI C]: void I_T2__Free ( I_T2 * s )
Frees allocated storage used internally by s. Does not free s itself.
All sequence types have the same structure, mandated by CORBA:
typedef struct I_T2 { unsigned long _maximum; unsigned long _length; long *_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 ANSI 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); ...
ILU_C_OBJECT
, a macro which
expands to the appropriate CORBA object type for the version of CORBA
being used. CORBA also
specifies that the type of the handle be called interface-name_type-name
.
A typedef of the CORBA-specified name to the ILU_C_OBJECT
type
is therefore generated for each object type.
In the example above, the type of the object instance would be I_O
.
Two binding procedures are specified for each object type. A binding procedure is a procedure that takes some name for an object instance, and returns the actual instance. Users of a module typically use a surrogate-side binding procedure, which takes the string binding handle of the object, and the most specific type ID of the object's type (if known). Suppliers of a module typically bind objects with a creation procedure, which takes an instance ID, a server on which to maintain the object, and arbitrary user data, and creates and returns the true instance of the object.
In general, for any object type T, the following ANSI C functions are defined:
[ANSI C]: OPTIONAL(T) T__CreateTrue ( OPTIONAL(RETAIN(char *)) instance-id, OPTIONAL(GLOBAL(ilu_Server)) server, OPTIONAL(PASS(void *)) user-data )
Creates a true instance of type T, exporting it with instance-id instance-id, exporting it
via server server-id, 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, the value of ILU_C_DefaultServer
will be used, if bound. If server is not specified, and
ILU_C_DefaultServer
is not specified, a NULL
pointer will be returned.
[ANSI C]: OPTIONAL(T) T__CreateFromSBH ( RETAIN(char *) sbh, OPTIONAL(char *) most-specific-type-ID)
Finds or creates an instance of T, using the instance-id and server-id specified in sbh, and the type specified by most-specific-type-ID.(9) If most-specific-type-ID is not specified, the most specific ILU type of T is used as the putative type. (The putative type is the most specific type of which the object instance may be assumed to be, even though the actual type of the instance may actually be a subtype of that type.)
[ANSI C]: extern ilu_Class
T__MSType
A value of type ilu_Class
which identifies the most specific ILU type of the 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
ANSI C header file would include the following statements:
typedef ILU_C_OBJECT I_T; I_T I_T__CreateTrue (ilu_string, ilu_Server server, void *user_data); I_T I_T__CreateFromSBH (char *sbh, char *mostSpecificTypeID); ilu_integer I_T_M (I_T, ILU_C_ENVIRONMENT *, ilu_real);
The functions I_T__CreateTrue
and I_T__CreateFromSBH
are used to create instances
of the class I_T
. I_T__CreateTrue
is used by servers
while I_T__CreateFromSBH
is used by clients. The pointer
returned in each case is the object instance and must be
passed with each method invocation.
In addition to its specified arguments, the method I_T_M
takes 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 second argument to each method. True procedures
must expect a pointer to this structure as the second
argument.
Finally, the ANSI C client calling the method for M
might be as follows:
#include "I.h" main (int ac, char **av) { double atof( ); I_T inst; int xx; double f; ILU_C_ENVIRONMENT ev; I__Initialize( ); f = atof (av[1]); inst = I_T__CreateFromSBH (av[2], NULL); xx = I_T_M (inst, &ev, f); if (ILU_C_SUCCESSFUL(&ev)) printf( "result is %d\n", xx ); else printf( "exception <%s> signalled on call to I_T_M\n", ILU_C_EXCEPTION_ID(&ev)); }
Note the call on the interface-specific client initialization procdedure I__Initialize
; these are described in a later section.
In this example, the string binding handle is obtained from standard input along with some floating-point value.
The class specific function I_T__CreateFromSBH
is called to
obtain the object instance. This function was passed
the string binding handle, and a NULL
pointer.
specific function. 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 ilu_real
argument f
. I_T_M
returns
an ilu_integer
value which is placed in xx
.
The true implementation of the method M
might be as follows:
ilu_integer server_I_T_M ( I_T h, ILU_C_ENVIRONMENT s, ilu_real u ) { 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.
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 class T3
inherits from the class T2
. Thus, five ANSI C methods
are generated for the interface I2
: I2_T1_M1
, I2_T2_M2
,
I2_T3_M1
, I2_T3_M2
, and I2_T3_M3
.
A module that implements true instances of T3
would have to define
all five true methods.
Each object type is represented by a TypeVector, which is a vector
of pointers to MethodBlock structs, one for each component type of
the object type, ordered in the proper class precedence for that object
type. Each MethodBlock struct contains a ilu_Class
value, followed
by a vector of pointers to the methods directly defined by that
ilu_Class
. There are two different TypeVectors for each object
type, one for the surrogate class of the type, and the other for the
true class of the type. The TypeVector for the surrogate class uses the
MethodBlocks of its supertypes; the TypeVector for the true class uses
its own MethodBlocks for both direct and inherited methods, as true
classes in the ANSI C implementation override all of their
methods. The TypeVectors, and MethodBlocks for true classes, are not
exported; the MethodBlocks for surrogate classes are, as they are used
by their subclasses.
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 TypeVector for the
object, till it finds a MethodBlock which contains the appropriate
ilu_Class on which this method is directly defined), then calling the
method pointer which is indexed in the MethodBlock's vector 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.
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, char * mstid ); ilu_integer calc_self_Div( calc_self, ILU_C_ENVIRONMENT *, ilu_integer, ilu_integer ); #endif
The method implementation for Div
in the true module must detect the
divide-by-zero condition and raise the exception(10):
long server_calc_self_Div (calc_self h, ILU_C_ENVIRONMENT *s, ilu_integer u, ilu_integer v) { calc_numerator n = 9; if ( v == 0 ) { s->returnCode = ex_ilu_ProtocolError; s->_major = ILU_C_USER_EXCEPTION; s->ptr = (void *) malloc(sizeof(calc_numerator)); *((calc_numerator *) (s->ptr)) = n; s->freeRoutine = (void (*) (void *)) free; 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, NULL); val = calc_self_Div (instance, &s, i, j); /* 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 ); } ...
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. 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_Environment *s, CORBA_integer u, CORBA_integer v) { calc_numerator n = 9; if ( v == 0 ) { s->returnCode = ex_ilu_ProtocolError; s->_major = CORBA_USER_EXCEPTION; s->ptr = (void *) malloc(sizeof(calc_numerator)); *((calc_numerator *) (s->ptr)) = n; s->freeRoutine = (void (*) (void *)) free; return( u ); } else return( u / v ); } main () { calc_self s; char * sbh; CORBA_Environment ev; 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 (ILU_C_ORB, &ev, s); 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 %x signalled <%s>.\n", s, CORBA_exception_id(&ev)); exit(1); } } }
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.
To generate ANSI C stubs from an ISL file, use the program c-stubber. Four files are generated from the `.isl' file:
% c-stubber foo.isl header file interface foo to ./foo.h... code for interface foo to ./foo-common.c... code for interface foo to ./foo-surrogate.c... code for server stubs of interface foo to ./foo-true.c... %
The option -renames renames-filename
may be used with
c-stubber
to specify particular ANSI C names for
ISL types.
It is sometimes necessary to have the ANSI C names of an ILU interface match some other naming scheme. A mechanism is provided to allow the programmer to specify the names of ANSI C language artifacts directly, and thus override the automatic ISL to ANSI 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 ANSI C-namewhere 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 ANSI C-name is the name the construct should have
in the generated
ANSI 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 ANSI C code. It can also create name conflicts
between different modules, unless names are carefully chosen.
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]: 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.
[ILU C API]: 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.
[ILU C API]: 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.
[ILU C API]: 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.
[ILU C API]: ilu_Class ILU_C_ClassRecordOfInstance (CORBA_Object)
Locking: unconstrained.
Returns the ilu_Class
value for the most specific type of an object instance.
[ILU C API]: ilu_string ILU_C_SBHOfObject ( CORBA_Object instance )
Locking: Main invariant holds.
Given an instance, returns a string form which is its name and contact information. The CORBA-specified
routine CORBA_ORB_object_to_string()
should typically be used instead.
[ILU C API]: OPTIONAL(CORBA_Object) ILU_C_SBHToObject (char * sbh, OPTIONAL(char *) mostSpecificTypeID, OPTIONAL(ilu_Class) putative_type)
Locking: Main invariant holds.
Given the string form of an object instance, along with information about its type, this routine returns an object, creating it if necessary.
[ILU C API]: 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.
[ILU C API]: 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()
.
[ILU C API]: OPTIONAL(GLOBAL(CORBA_Object)) ILU_C_LookupObject ( RETAIN(char *) oid, ilu_Class putative-class )
Locking: Main invariant holds.
Finds and returns the object specified by oid by consulting the local domain registry of objects. putative-class is the type that the object is expected to be of, though the type of the actual object returned may be a subtype of putative-class.
[ILU C API]: void ILU_C_Run (void)
Locking: Main invariant holds.
Called to animate a server or other program. Invokes the event handling loop. Never returns.
[ILU C API]: ilu_Server ILU_C_DefaultServer
Locking: Main invariant holds.
Can be set to choose the default server. Note that the default port must be chosen in lockstep.
[ILU C API]: ilu_Port ILU_C_DefaultPort
Locking: Main invariant holds.
Can be set to determine the default port.
[ILU C API]: ilu_Server ILU_C_InitializeServer (OPTIONAL(RETAIN(char *)) serverID, OPTIONAL(GLOBAL(ilu_ObjectTable)) obj_tab, OPTIONAL(RETAIN(char *)) protocol, OPTIONAL(RETAIN(char *)) transport, ilu_boolean setdefaultport)
Locking: Main invariant holds.
Creates and returns an ilu_Server
with ID serverID, object mapping table obj_tab, using protocol protocol over a transport of type 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 setdefaultport, an ilu_Port
will automatically be created and added to the ilu_Server
. protocol is a string of the form "sunrpc_"
. It defaults using Sun RPC
. transport is a string of the form "yyy_localhost_xxx"
, where yyy is one of tcp
or udp
, and xxx is a decimal number indicating which UNIX port to listen on, or 0 if you wish the system to select the port. The default transport value, if NULL
is passed, is "tcp_localhost_0"
. If setdefaultport is true, the newly created ilu_Port
will become the default port of the ilu_Server
.
ILU supports either CORBA 1.1 and 1.2, depending on how it is installed at your site.(11) A number of macros are defined to make programs less dependent on which version they use.
Expands to either CORBA_Object
or Object
.
Expands to either CORBA_Environment
or Environment
.
Expands to either StExcep_NO_EXCEPTION
or CORBA_NO_EXCEPTION
.
Expands to either StExcep_USER_EXCEPTION
or CORBA_USER_EXCEPTION
.
Expands to either StExcep_SYSTEM_EXCEPTION
or 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 either exception_value(ev)
or CORBA_exception_value(ev)
.
Macro: ILU_C_EXCEPTION_FREE ( ILU_C_ENVIRONMENT * ev )
Expands to either exception_free(ev)
or CORBA_exception_free(ev)
.
Go to the previous, next section.