Digital DCE for OpenVMS VAX and OpenVMS Alpha
Product Guide


Previous Contents Index

14.4.4.1 Error Handling

A binding callout routine returns error_status_ok when it successfully modifies the binding handle or decides that no action is necessary. This causes the client stub to initiate the remote procedure call.

When the binding callout routine returns an error status, the client stub does not initiate a remote procedure call. If auto_handle is being used, the client stub will attempt to locate another server of the interface and once again call the binding callout routine. Otherwise, the client stub executes its normal error handling logic.

A binding callout routine for a client using auto_handle can return rpc_s_no_more_bindings to prevent the client stub from trying to locate another server. The client stub will then execute its normal error handling logic.

By default, a client stub handles an error condition by raising an exception. If a binding callout routine returns an rpc_s_ status code, the client stub raises the matching rpc_x_ exception. If a binding callout routine returns any other error status, it is usually raised as an unknown status exception.

For an operation containing a comm_status parameter, the client stub handles an error condition by returning the error status value in the comm_status parameter. A binding callout routine can return any error status value to the client application code if the IDL operations are specified with comm_status parameters.

A binding callout routine can raise a user-defined exception rather than return a status code if it prefers to report application-specific error conditions back to the client application code via exceptions.

14.4.5 Predefined Binding Callout Routine

There is one predefined binding callout routine in the DCE library that may be suitable for some applications. To select this routine, specify a binding_callout(rpc_ss_bind_authn_client) ACF attribute.

rpc_ss_bind_authn_client matches the function prototype in the previous section, Generated Header File. It authenticates the client identity to the server, thereby allowing for one-way authentication. In other words, the client does not care which server principal receives the remote procedure call request, but the server verifies that the client is who the client claims to be.

rpc_ss_bind_authn_client does the following:

14.5 Extensions to IDL Data Structures

The following additional data structures are available from the IDL compiler on Digital platforms. These will be Digital extensions to OSF DCE and may not be portable to other vendors' implementations of DCE.

To use these additional data structures, you should specify the -standard extended option on the IDL command line, as previously described.

14.5.1 Unique Pointer

A unique pointer is more flexible than a reference pointer. However, both types of pointers share several important characteristics.

A unique pointer has the following characteristics:

Unique pointers are similar to reference pointers in the following ways:

With regard to performance, unique pointers have an advantage over full pointers because unique pointers do not support the referencing of common data by more than one pointer (aliasing), and they are significantly more flexible than reference pointers because they can have a value of NULL.

Unique pointers are particularly suitable for creating optional parameters (because you can specify them as NULL) and for simple tree or singly linked-list data structures. You specify the three different levels of pointers by attributes, as follows:
[ref] reference pointers
[unique] unique pointers
[ptr] full pointers

The following example shows how a unique pointer can be used:


    [ 
 uuid(D37A0E80-5D23-11C9-B199-08002B13D56D) 
    ] interface Unique_ptrs 
    { 
 typedef [ref]    long *r_ptr; 
 typedef [unique] long *u_ptr; 
 typedef [ptr]    long *f_ptr; 
 
 void op1 ( 
   [ref,in,out,string]  char *my_rname, 
   [unique,in,out,string] char *my_uname, 
   [ptr,in,out,string]  char *my_pname 
   ); 
     } 

14.5.2 Array Extensions

The Digital DCE IDL compiler implements an extended array syntax specified by OSF. These extensions have lifted previous restrictions in array syntax. Previously, 0 (zero) was the only valid lower bound in array dimensions. Previously, only the first dimension of an array could be conformant (size determined at runtime) or varying (the amount of data transferred determined at runtime).

14.5.2.1 min_is Attribute

The min_is attribute is used to specify the variable(s) from which the values of one or more lower bounds of the array will be obtained at runtime. If any dimension of an array has an unspecified lower bound, the array must have a min_is attribute. A variable must be identified for each such dimension. The following examples show the syntax of the min_is attribute.


/* Assume values of variables are as follows 
    long a = -10; 
    long b = -20; 
    long c = -30; 
*/ 
 
long [min_is(a)] g1[*..10];          /* g1[-10..10] */ 
long [min_is(a)] g2[*..10][4];       /* g2[-10..10[0..3] */ 
long [min_is(a,b)] g3[*..10][*..20]; /* g3[-10..10][-20..20] */ 
long [min_is(,b)] g4[2][*..20];      /* g4[0..1][-20..20] */ 
long [min_is(a,,c)] g5[*.7][2.9][*.8];/* g5[-10.7][2.9][-30.8]*/ 
long [min_is(a,b,)] g6[*.10][*.20][3.8];/* g6[-10.10][-20.20][3.8]*/ 

The following examples show the min_is attribute being applied to the first dimension of an array in an IDL type definition and parameter declaration, and how the definition or parameter is translated into its C equivalent.

IDL Type Definition:


     typedef struct { 
              long n; 
       [min_is(n)] long fa3[*..10][-4..1][-1..2] 
     } t2; 

C Translation:


     typedef struct  { 
       idl_long_int n; 
       idl_long_int fa3[1][6][4]; 
     } t2; 

IDL Parameter Declaration:


     [in,out,min_is(n)] long fa3[*..10][-4..1][-1..2] 

C Translation:


     /* [in, out] */ idl_long_int fa3[][6][4] 

14.5.2.2 Conformance in Dimensions Other Than the First

If a multidimensional array is conformant in a dimension other than the first, the C description for this array, which is located in the header file generated by the IDL compiler, will be a one-dimensional conformant array of the appropriate element type. This occurs because there is no "natural" C binding for conformance in dimensions other than the first.

The following examples show how IDL type definitions and parameter declarations that contain bounds in dimensions other than the first are translated into their C equivalents at runtime.

IDL Type Definition:


     typedef struct { 
         long a; 
         long e; 
         [max_is(,,e),min_is(a)] long g7[*..1][2..9][3..*]; 
     } t3; 

C Translation:


     typedef struct  { 
       idl_long_int a; 
       idl_long_int e; 
       idl_long_int g7[1]; 

IDL Parameter Declaration:


     [in,out,max_is(,,e),min_is(a)] long g7[*..1][2..9][3..*]; 

C Translation:


     /* [in, out] */ idl_long_int g7[] 

Arrays that have a nonzero first lower bound and a first upper bound that is determined at runtime are translated into the equivalent C representation of a conformant array, as shown in the following IDL type definition and parameter declaration examples:

IDL Type Definition:


     typedef struct  { 
                long s; 
                [size_is(s)] long fa3[3..*][-4..1][-1..2]; 
     } t1; 

C Translation:


     typedef struct  { 
       idl_long_int s; 
       idl_long_int fa3[1][6][4]; 
     } t1; 

IDL Parameter Declaration:


     [in,out,size_is(s)] long fa3[3..*][-4..1][-1..2] 

C Translation:


     /* [in, out] */ idl_long_int fa3[][6][4] 

14.5.3 Nonencapsulated Unions

An IDL union must be discriminated. IDL provides two fundamental types of discriminated unions: encapsulated and nonencapsulated. Encapsulated unions provide compatibility with DECrpc Version 1.0 or 1.1. Nonencapsulated unions are an extension to the OSF DCE IDL compiler. The OSF DCE Application Development Guide describes encapsulated unions. The following paragraphs describe nonencapsulated unions.

To define a nonencapsulated union, use the following syntax:


[switch_type(datatype)] union [tag]
{ 
case
... 
[default_case]
} 

If a tag is supplied, it can be used in a type_specifier of the form shown in the section describing unions.

A parameter or a structure field that is a nonencapsulated union must have an attribute attached to it. This attribute has the form:


switch_is(attr_var)

attr_var is the name of the parameter or structure field that is the discriminator for the union.

If a nonencapsulated union is used as a structure field, the discriminator of the union must be a field of the same structure. If a nonencapsulated union is used as a parameter of an operation, the discriminator must be another parameter of the same operation.

The following example shows uses of a nonencapsulated union.


   typedef 
     [switch_type(long)] union { 
       [case (1,3)] float a_float; 
       [case (2)] short b_short; 
       [default] ; /* An empty arm. Nothing is shipped. */ 
     } n_e_union_t; 
 
 
   typedef 
     struct { 
 long a; /* The discriminant for the union later in this struct. */ 
       [switch_is (a)] n_e_union_t b; 
     } a_struct; 
 
 
    /* Note switch can follow union in operation */ 
   void op1 ( 
        [in] handle_t h, 
        [in,switch_is (s)] n_e_union_t u, 
        [in] long s  ); 

14.5.4 Defining Exceptions with IDL

One set of exceptions can always be returned from the server to the client. These exceptions are referred to as system exceptions. The following is a full list of system exceptions:

In addition, an interface definition may specify a set of other exceptions that the operations of that interface may return to the client. These exceptions are referred to as user-defined exceptions. If a server implementation of an operation raises an exception that is neither a system exception nor a user-defined exception, the exception returned to the client is rpc_x_unknown_remote_fault.

If an exception in the implementation of a server operation occurs during server execution, the server terminates the operation and propagates the exception to the client in a manner similar to the way system exceptions are propagated. You can declare user-defined exceptions in the IDL by using the exceptions interface attribute, which has the following syntax:


exceptions  (<IDENTIFIER>[, <IDENTIFIER> ...) 

The following is a sample declaration of an exceptions attribute:


[uuid(06255501-08AF-11CB-8C4F-08002B13D56D), 
version (1.1), 
  exceptions ( 
      exc_e_exquota, 
      binop_e_aborted, 
      binop_e_too_busy, 
      binop_e_shutdown) 
] interface binop 
  { 
      long binop_add( 
           [in] long a, 
           [in] long b 
           ); 
   } 

By default, the IDL defines and initializes all exceptions under a once block in the generated stubs. However, if you want to share exception names in multiple interfaces or you desire greater control over how these exceptions are defined and initialized, you can use the ACF extern_exceptions attribute. This attribute, when declared, disables the automated mechanism that the IDL uses to define and initialize exceptions. See the chapter describing the Attribute Configuration Language in the OSF DCE Application Development Guide for more information on the extern_exceptions attribute.

Because exceptions are associated with operation implementation, they are not imported into other interfaces by way of the import statement.

14.6 Syntax for Unions

The following is the complete extended union syntax expressed in the Backus Naur Format (BNF) for IDL. This syntax is described in the OSF DCE Application Development Guide. This section is provided to show the updated BNF for nonencapsulated unions.


<TAGGED_UNION_DECLARATOR>  ::= "union" <TAG>  
 | <TAGGED_UNION> 
 
<UNION_TYPE>  ::= "union" <UNION_SWITCH>  "{" <UNION_BODY>  "}" 
 | "union" "{" <UNION_BODY_N_E>  "}" 
 
<UNION_SWITCH>  ::= "switch" "(" <SWITCH_TYPE_SPEC>  <IDENTIFIER>  ")" [ <UNION_NAME>  ] 
 
<SWITCH_TYPE_SPEC>  ::= <PRIMITIVE_INTEGER_TYPE>  
 | <CHAR_TYPE> 
 | <BOOLEAN_TYPE> 
 | <ENUMERATION_TYPE> 
 
<TAGGED_UNION>  ::= "union" <TAG>  <UNION_SWITCH>  "{" <UNION_BODY>  "}" 
 | "union" <TAG>  "{" <UNION_BODY_N_E>  "}" 
 
<UNION_NAME>  ::= <IDENTIFIER> 
 
<UNION_BODY>  ::= <UNION_CASE>  [  <UNION_CASE>  ] ... 
 
<UNION_BODY_N_E>  ::=  <UNION_CASE_N_E>  [ <UNION_CASE_N_E>  ] ... 
 
<UNION_CASE>  ::= <UNION_CASE_LABEL>  [ <UNION_CASE_LABEL>  ] ... <UNION_ARM> 
 | <DEFAULT_CASE> 
 
<UNION_CASE_N_E>  ::= <UNION_CASE_LABEL_N_E>  <UNION_ARM> 
 | <DEFAULT_CASE_N_E>  
 
<UNION_CASE_LABEL>  ::= "case" <CONST_EXP>  ":" 
 
<UNION_CASE_LABEL_N_E>  ::= "[" "case" "(" <CONST_EXP>  [ , <CONST_EXP> ] ...")" "]" 
 
<DEFAULT_CASE>  ::= "default" ":" <UNION_ARM> 
 
<DEFAULT_CASE_N_E>  ::= "[" "default" "]" <UNION_ARM> 
 
<UNION_ARM>  ::= [ <FIELD_DECLARATOR>  ] ";" 
 
<UNION_TYPE_SWITCH_ATTR>  ::= "switch_type" "(" <SWITCH_TYPE_SPEC>  ")" 
 
<UNION_INSTANCE_SWITCH_ATTR>  ::= "switch_is" "(" <ATTR_VAR>  ")" 

14.7 Operation Attributes: Memory Management

Use the reflect_deletions attribute to mirror the release of memory from server pointer targets to client pointer targets. When you use the reflect_deletions attribute, memory occupied by pointer targets on the client will be released when the corresponding pointer targets on the server are released. This is true only for pointer targets that are components of [in] parameters of the operation.

By default, the mechanism used by RPC to release the pointer targets is the language free() function unless the client code is executing as part of RPC server application code, in which case the rpc_ss_free() function is used. You can override the default by calling rpc_ss_set_client_alloc_free or rpc_ss_swap_client_alloc_free before the call to the remote operation.


Previous Next Contents Index