12 — Developing Distributed Applications with FORTRAN


[Previous] [Next] [Contents] [Index]


12.1 Overview of Applications with FORTRAN

This chapter explains how to use DIGITAL FORTRAN® in the development of distributed applications that make remote procedure calls.

This chapter provides the following information:

12.2 Interoperability and Portability

In general, an application you create in the Gradient DCE for Tru64 UNIX RPC environment will interoperate with other DCE RPC applications and will port to other DCE platforms if it complies with the appropriate programming language standards. More specifically:

Typically, applications created in the DCE RPC environment are written in the C programming language. However, if you use the DIGITAL FORTRAN support in Gradient DCE for Tru64 UNIX, the application will be subject to the following portability constraint:

12.3 Remote Procedure Calls Using FORTRAN — Example

The Gradient DCE for Tru64 UNIX IDL compiler provides similar support for applications written in DIGITAL FORTRAN as that provided for applications written in C. That is, you can write an RPC client in DIGITAL FORTRAN or you can write one or more manager routines in the server side of the application in DIGITAL FORTRAN. If you are unfamiliar with the tasks involved in developing an RPC application, see the chapter about application building in the OSF DCE Application Development Guide.

The DIGITAL FORTRAN support consists of stubs that use DIGITAL FORTRAN linkage conventions and a file that contains DIGITAL FORTRAN definitions of the constants and types declared in an interface definition. (These conventions and definitions are explained in Remote Procedure Calls Using FORTRAN — Example.)

The following sections present a comprehensive example that demonstrates how you can create the various parts of a simple, distributed payroll application using DIGITAL FORTRAN.

The important features of this example are as follows:

12.3.1 Where to Obtain the Example Application Files

All of the example application files referenced in this chapter are located in the following directory in your kit:

/usr/examples/dce/rpc/payroll

The next table lists application files that normally would be created by the programmer for an application. To demonstrate application building, these application files are provided for you in the software kit. The second table in Compiling the Interface with the IDL Compiler lists the files generated by the IDL compiler for the example application.

Before you execute any of the example compilations, builds, or run commands in this chapter, copy all of the files listed in the first table to an empty directory. Entegrity recommends that you read the file named README in the same subdirectory. Then build and run the examples.

Table 12-1: Example Files Created by the Programmer

Filename File Description
payroll.idl

The interface definition file that contains the application programming interface (API) to the remote procedure call calculate_pay( ).

print_pay.for

The FORTRAN source file for the client side of the application.

server.c

The FORTRAN source file that contains the initialization code for the server side of the application.

manager.for

The FORTRAN source file for the server side of the application.

Makefile.unix

The description file that builds the example application.

payroll.dat

The data input file for the example application.

The programs, procedures, and data files in the payroll example should be the same in this chapter and in the specified subdirectory that came with your Gradient DCE for Tru64 UNIX software kit. For example, file payroll.idl as it appears in The Interface File and Data File (payroll.idl and payroll.dat) should be identical to the following file:

/usr/examples/dce/rpc/payroll/payroll.idl

For all of the example files, if there is a difference between the file as shown in this chapter and the file in the subdirectory, assume that the file in the subdirectory is the correct one.

12.3.2 The Interface File and Data File (payroll.idl and payroll.dat)

The following interface, named payroll.idl, is part of the example application. The name of the remote procedure in the interface is calculate_pay( ). The interface does not indicate that this procedure is written in DIGITAL FORTRAN.

/*
**  Copyright (c) 1993 by
**      Digital Equipment Corporation, Maynard, Mass.
**
*/
    

[
uuid(d1b14181-6543-11ca-ba11-08002b17908e),
version(1.0)
]
interface payroll
{
    const long string_data_len = 7;

    typedef struct {
        [string] char grade[string_data_len + 1];
          /*Storage for string must include space for null terminator*/
        short   regular_hours;
        short   overtime_hours;
    } timecard;

    void calculate_pay(
        [in] timecard cards[1..7],
        [out] long *pay
    );
}

The next part of the example is the data file payroll.dat, which the client side of the application reads. The facts about each employee appear in 8 records. The first record contains the employee's name (40 characters) and grade (7 characters). Records 2 to 8 contain the number of regular hours and overtime hours worked on Monday to Sunday.

NOTE: The timecard structure defined in payroll.idl does not specify the employee's name in the data going to the remote procedure.

Jerry Harrison                          FOREMAN
 8 1
 8 1
 8 2
 8 2
 8 1
 0 4
 0 0
Tony Hardiman                           WORKER
 8 0
 8 0
 8 0
 8 2
 8 0
 0 4
 0 0
Mary Flynn                              WORKER
 8 1
 8 1
 8 2
 8 0
 8 1
 0 4
 0 0

12.3.3 Compiling the Interface with the IDL Compiler

To compile an RPC interface, you must use the idl command to invoke the IDL compiler. To compile an RPC interface for a DIGITAL FORTRAN application, you must select the following IDL options:

The following example command illustrates how to invoke the IDL compiler to compile the sample DIGITAL FORTRAN application interface:

% idl payroll.idl -lang fortran -standard extended

As a result of this command, the IDL compiler generates the files listed in the next table.

Table 12-2: Example Files Created by IDL

Filename File Description
payroll_cstub.o

The stub file generated by the IDL compiler for the client side of the application.

payroll_sstub.o

The stub file generated by the IDL compiler for the server side of the application.

payroll.for

An include file that emulates the C language header file (.h) and that documents the valid syntax for subroutine calls that are used in the FORTRAN source files. This file will be called out in Makefile.unix and linked with the other application files because it refers to constants and types defined in the interface definition.

payroll.for_h

A file generated by the IDL compiler that is used to build the stub files.

File payroll.for, as generated by the IDL compiler, is next.

C     Generated by IDL compiler version DEC DCE Vn.n.n-n
C
C     The following statements must appear in application code
C     INCLUDE 'NBASE.FOR'

      INTEGER*4 STRING_DATA_LEN
      PARAMETER (STRING_DATA_LEN=7)

      STRUCTURE /TIMECARD/
          CHARACTER*8 GRADE
          INTEGER*2 REGULAR_HOURS
          INTEGER*2 OVERTIME_HOURS
      END STRUCTURE

C      SUBROUTINE CALCULATE_PAY(CARDS, PAY)
C      RECORD /TIMECARD/ CARDS(7)
C      INTEGER*4 PAY

As you read this chapter, it is important to remember that the interface defined in file payroll.idl appears as DIGITAL FORTRAN statements in file payroll.for. As a specific instance, consider the overtime hours field. Its definition appears in payroll.idl as the statement short overtime_hours, and in payroll.for as the statement INTEGER*2 OVERTIME_HOURS. The overtime hours data in file payroll.dat is read into a data item of this type.

12.3.4 The Client Application Code for the Interface (print_pay.for)

Suppose that the directory in which the interface was compiled also contains file print_pay.for. This is the source file for the client side of the distributed application. Its contents follow.

C				This is the client side of a payroll application that
C				   uses remote procedure calls.
C
        PROGRAM PRINT_PAY
        INCLUDE 'PAYROLL.FOR'    ! Created by the IDL compiler from
                                 !    file PAYROLL.IDL.
C				COPYRIGHT (C) 1993 BY DIGITAL EQUIPMENT CORP., MAYNARD MASS.
C       The structure of a time card is described in the included file.
        RECORD /TIMECARD/ CARDS(7)
        CHARACTER*40 NAME
        CHARACTER*8  GRADE
        INTEGER*4 PAY
        INTEGER*4 I
C
C				Read eight records for the current employee.
   10   READ (4, 9000, END=100) NAME, GRADE  ! First record
 9000   FORMAT (A40, A8)
        DO 20 I = 1, 7   ! Second through eighth records
           READ (4,9010) CARDS(I).REGULAR_HOURS, CARDS(I).OVERTIME_HOURS
 9010      FORMAT (I2, I2)
           CARDS(I).GRADE = GRADE
   20   CONTINUE
C
C				Call remote procedure CALCULATE_PAY to calculate the gross pay.
        CALL CALCULATE_PAY (CARDS, PAY)
C				Display the current employee's name and gross pay.
        WRITE  (6, 9020) NAME,     PAY
 9020   FORMAT (1X,      A40,  1X, I4  )
        GO TO 10
C
  100   STOP
C
        END

To compile and link the client program print_pay.for, which at runtime makes remote procedure calls to a server that supports the payroll interface, use the following commands.

% fortran -c print_pay.for

% ld -o print_pay print_pay.o payroll_cstub.o 

-lfor -lutil -lUfor -lm -lots -ldce -lpthreads -lmach -lc_r -lm

Instead of using these two commands directly to build the client part of the application, you can use make to build the entire application using the supplied Makefile, called Makefile.unix. See Section 12.3.8 on page 146 and Section 12.3.9 on page 148 for information about building and running this example.

This program reads its data from DIGITAL FORTRAN logical unit 4. A command in Makefile.unix defines the logical unit.

12.3.5 The Server Initialization File (server.c)

Because all programming interfaces to the RPC runtime are specified in C, you must write the code that sets up the server in C. In this example, the server setup code (also called the initialization code) is in file server.c, shown next.

/* This is program SERVER.C that sets up the server for 
   the application code whose origin is FORTRAN 
   subroutine CALCULATE PAY.               */

/*
** Copyright (c) 1993 by
**     Digital Equipment Corporation, Maynard, Mass.
**
*/

#include <stdio.h>
#include <file.h>
#include <dce/dce_error.h>
#include "payroll.for_h"  /* The IDL compiler created this file from
                             file PAYROLL.IDL.                    */

static char error_buf[dce_c_error_string_len+1];
static char *error_text(st)
    error_status_t st;
{
    error_status_t rst;
    dce_error_inq_text(st, error_buf, &rst);
    return error_buf;
}
 

main()
{
  error_status_t st;
  rpc_binding_vector_p_t bvec;

  /* Register all supported protocol sequences with the runtime. */
  rpc_server_use_all_protseqs(
        rpc_c_protseq_max_calls_default,
        &st
  );
  if (st != error_status_ok)
  {
   fprintf(stderr, "Can't use protocol sequence - %s\n",error_text(st));
   exit(1);
  }


    /* Register the server interface with the runtime.                */
    rpc_server_register_if(
        payroll_v1_0_s_ifspec,  /* From the IDL compiler;             */
                                /* "v1_0" comes from the statement    */
                                /* "version(1.0)" in file PAYROLL.IDL.*/
        NULL,
        NULL,
        &st
    );
    if (st != error_status_ok) 
    {
        printf("Can't register interface - %s\n", error_text(st));
        exit(1);
    }

    /* Get the address of a vector of server binding handles.  The
       call to routine rpc_server_use_all_protseqs() directed the
       runtime to create the binding handles.                      */
    rpc_server_inq_bindings(&bvec, &st);
    if (st != error_status_ok) 
    {
        printf("Can't inquire bindings - %s\n", error_text(st));
        exit(1);
    }

    /*Place server address information into the local endpoint map.*/
    rpc_ep_register(
        payroll_v1_0_s_ifspec,
        bvec,
        NULL, 
        (idl_char*)"FORTRAN Payroll Test Server",
        &st
    );
    if (st != error_status_ok) 
    {
        printf("Can't register ep - %s\n", error_text(st));
    }

    /* Place server address information into the name service database. */
    rpc_ns_binding_export(
        rpc_c_ns_syntax_default,
        (idl_char*)".:/FORTRAN_payroll_mynode",
        payroll_v1_0_s_ifspec, 
        bvec,
        NULL, 
        &st
    );
    if (st != error_status_ok) 
    {
        printf("Can't export to name service - %s\n", error_text(st));
    }

    /* Tell the runtime to listen for remote procedure calls.
       Also, FORTRAN cannot support multiple threads of execution. */ 
    rpc_server_listen((int)1, &st);
    if (st != error_status_ok)
        fprintf(stderr, "Error listening: %s\n", error_text(st));

}

12.3.6 The Server Application Code for the Interface (manager.for)

The server application code, written in DIGITAL FORTRAN, is declared in file payroll.idl as calculate_pay( ). File manager.for contains subroutine calculate_pay as follows:

        SUBROUTINE CALCULATE_PAY(CARDS, PAY)
        INCLUDE 'PAYROLL.FOR'    ! Created by the IDL compiler from
                                 ! file PAYROLL.IDL.
C

C				COPYRIGHT (C) 1993 BY DIGITAL EQUIPMENT CORP., MAYNARD MASS.
C       The structure of a time card is described in included 
C       file PAYROLL.FOR.

        RECORD /TIMECARD/ CARDS(7)
        INTEGER*4 PAY
        INTEGER*4 I

        PAY = 0
        DO 10 I = 1, 7
C				    The basic hourly wage is $6.00.
            PAY = PAY + 6 * CARDS(I).REGULAR_HOURS
C				    The following comparison does not include last character 
C				       of GRADE, because it arrives as a null terminator.
            IF (CARDS(I).GRADE(1:STRING_DATA_LEN) .EQ. 'FOREMAN') THEN
C				        The overtime hourly wage for a foreman is $12.00.
                PAY = PAY + 12 * CARDS(I).OVERTIME_HOURS
            ELSE
C				        The overtime hourly wage for a worker is $9.00.
                PAY = PAY +  9 * CARDS(I).OVERTIME_HOURS
            END IF
   10   CONTINUE

        RETURN
        END

To create the file server, which at runtime responds to remote procedure calls from a client that supports the payroll interface, use the following commands.

% cc -c server.c
% fortran -c manager.for
% ld -o server server.o manager.o payroll_sstub.o 
-lfor -lutil -lUfor -lm -lots -ldce -lpthreads -lmach -lc_r -lm

Instead of using these commands directly to build the server part of the application, you can use make to build the entire application (see Section 12.3.8 on page 146).

12.3.7 Client and Server Bindings

In order to make remote procedure calls, client applications must be bound to server applications. This is illustrated in the client program print_pay.for shown in Section 12.3.4 on page 142. The source code in the client program uses the default [auto_handle] binding, which is enabled by the following source code:

C				Call remote procedure CALCULATE_PAY to 
C       calculate the gross pay.

        CALL CALCULATE_PAY (CARDS, PAY)

When you run make (described in Building the Example (Makefile.unix)) or manually compile the application, a message is displayed about assuming [auto_handle].

For more information about client and server bindings, see the chapter on basic DCE RPC runtime operations in the OSF DCE Application Development Guide.

12.3.8 Building the Example (Makefile.unix)

You can build the payroll example with make by using file Makefile.unix. Since the supplied Makefile has a .unix filename extension, you must use the -f option to the make command, as follows:

% make -f Makefile.unix 

The contents of Makefile.unix follow.

#
#                      COPYRIGHT (C) 1993 BY
#                 DIGITAL EQUIPMENT CORPORATION, MAYNARD
#                  MASSACHUSETTS.  ALL RIGHTS RESERVED.
#
# THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
# ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE 
# INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY 
# OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE 
# TO ANY OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE SOFTWARE 
# IS HEREBY TRANSFERRED.
#
# THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT 
# NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
# EQUIPMENT CORPORATION.
#
# DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
# SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
#

DCELIBS = $(LIBLOC) -ldce -lpthreads -lmach -lc_r -lm
FFLAGS = -c
FLIBS = -lfor -lutil -lUfor -lm -lots
FORTRAN = f77
I18NLIB = 
IDL = idl
IDLFLAGS = -trace all -lang fortran -standard extended
LINKFLAGS = 

# Default target - build client and server
all : print_pay server
				@- cp /dev/null build.timestamp

# Target to build "local" (non-RPC) application in single image
local : local_print_pay
				@- cp /dev/null buildl.timestamp

# Target to run local application
run_local :
				FORT4=payroll.dat; export FORT4; local_print_pay

# Target to clean up non-source files
clean :
				@- rm server server.o manager.o payroll_sstub.o
				@- rm print_pay print_pay.o payroll_cstub.o
				@- rm payroll.for payroll.for_h
				@- rm build.timestamp
				@- rm buildl.timestamp local_print_pay
				@- rm server.log

server : server.o manager.o payroll_sstub.o
$(CC) $(LINKFLAGS) -o $@ server.o manager.o payroll_sstub.o \
$(FLIBS) $(DCELIBS)


print_pay : print_pay.o payroll_cstub.o
$(FORTRAN) $(LINKFLAGS) -o $@ print_pay.o payroll_cstub.o \
$(FLIBS) $(DCELIBS)

print_pay.o : print_pay.for payroll.for
$(FORTRAN) $(FFLAGS) -o $@ print_pay.for

payroll.for : payroll.idl
$(IDL) $(IDLFLAGS) payroll.idl

payroll_cstub.o : payroll.idl
$(IDL) $(IDLFLAGS) payroll.idl

server.o : server.c payroll.for_h
$(CC) $(CFLAGS) -o $@ server.c

payroll.for_h : payroll.idl
$(IDL) $(IDLFLAGS) payroll.idl

manager.o : manager.for payroll.for
$(FORTRAN) $(FFLAGS) -o $@ manager.for

payroll_sstub.obj : payroll.idl
$(IDL) $(IDLFLAGS) payroll.idl

local_print_pay : print_pay.o manager.o
$(FORTRAN) $(LINKFLAGS) -o $@ print_pay.o manager.o $(FLIBS) $(I18NLIB)

12.3.9 Running the Example

To run the sample application, perform the following steps:

  1. Start the server process and run it as a background job:

    % setenv RPC_DEFAULT_ENTRY 
    ".:/FORTRAN_payroll_mynode"
    % server &
    

  2. Run the client:

    % setenv FORT4 payroll.dat
    % print_pay
    

    The program displays the following output:

    Jerry Harrison                   372
    Tony Hardiman                294
    Mary Flynn                          321
    FORTRAN STOP
    Deleting server process...
    End of sample application
    

  3. Bring the server process to the foreground and terminate it:

    % fg
    % CTRL/C
    

    The output from building this application includes files client and server. You can use these executable programs in separate client and server processes.

12.4 Remote Procedure Calls Using FORTRAN — Reference

Remote Procedure Calls Using FORTRAN — Example contains a comprehensive example that introduces creating distributed applications with DIGITAL FORTRAN program units. This section goes beyond the example to provide reference information and explain general concepts about creating these distributed applications.

12.4.1 The FORTRAN Compiler Option

If you are generating stubs and include files for application code written in DIGITAL FORTRAN, you must specify it as the language of choice when you compile the application's IDL file. To specify the DIGITAL FORTRAN language, specify -lang fortran; the default value is -lang c.

In the remainder of this chapter, the phrase "FORTRAN option" refers to the IDL command that specifies DIGITAL FORTRAN. Examples of the IDL command and specification are presented in Compiling the Interface with the IDL Compiler.

Any client or server stub files that the FORTRAN option generates use the DIGITAL FORTRAN linkage conventions. This means that all parameters are passed by reference (see Section 12.4.5.1 on page 153 for more information). In addition, all identifiers are converted to uppercase.

The FORTRAN option generates the file filename.for, which includes DIGITAL FORTRAN declarations of the constants and types declared in the IDL file. The .for file also includes, for each operation declared in the IDL file, a set of comments that describes the signature of the operation in DIGITAL FORTRAN terms.

In addition, the FORTRAN option generates the file filename.for_h. This file is used for generating the client and server stubs. It is also needed for generating DIGITAL FORTRAN stubs for any interface that imports this interface.

Consider the header option whose syntax is -header. If you specify both the FORTRAN option and the header option to the IDL compiler, the following rules govern the compiler's placement of the files filename.for and filename.for_h.

12.4.2 Restrictions on the Use of FORTRAN

This section discusses restrictions on distributed applications written in DIGITAL FORTRAN that make remote procedure calls. These restrictions are on interfaces and stubs, and on runtime operations.

12.4.3 IDL Constant Declarations

A constant declaration either gives a name to an integer or string constant or gives a second name to a constant that has already been given a name. Examples of these declarations follow:

const long array_size = 100;
const char jsb = "Johann \"Sebastian' Bach";
const long a_size = array_size;
const boolean untruth = FALSE;

For all IDL constant declarations, equivalent PARAMETER statements are generated in the corresponding file filename.for. For example:

INTEGER*4 ARRAY_SIZE 
PARAMETER (ARRAY_SIZE=100)

CHARACTER*(*) JSB
PARAMETER (JSB='Johann "Sebastian'' Bach')

INTEGER*4 A_SIZE
PARAMETER (A_SIZE=ARRAY_SIZE)

LOGICAL*1 UNTRUTH
PARAMETER (UNTRUTH=.FALSE.)


All integer constants are declared as INTEGER*4.

All void * constants are ignored.

A nonprinting character that appears within a character or string constant is replaced by a question mark (?).

12.4.4 Type Mapping

An IDL type that is a synonym for another type is presented to DIGITAL FORTRAN as the type for which the synonym is defined. For example, suppose that the IDL file contains the following statement:

typedef foo bar;

Then, all instances of IDL type bar are presented to DIGITAL FORTRAN as of type foo.

The next table describes the mappings from IDL types to DIGITAL FORTRAN types.

Table 12-3: Mappings for IDL Types

IDL Data Type FORTRAN Data Type Comments
arrays

See notes 8 and 9

boolean

LOGICAL*1

byte

BYTE

char

CHARACTER

context handle

INTEGER*4

double

REAL*8

See note 3

enum

INTEGER*4

error_status_t

INTEGER*4

See note 4

float

REAL*4

handle_t

HANDLE_T

See Section 12.4.7 on page 154

hyper

IDL_HYPER_INT

See Section 12.4.7 on page 154

ISO_MULTI_LINGUAL

ISO_MULTI_LINGUAL

See Section 12.4.7 on page 154

ISO_UCS

ISO_UCS

See Section 12.4.7 on page 154

long

INTEGER*4

pipe

No mapping

pointer

INTEGER*4

See note 10

short

INTEGER*2

small

INTEGER*2

See note 1

struct

STRUCTURE

See notes 5 and 6

union

UNION

See note 7

unsigned hyper

IDL_UHYPER_INT

See Section 12.4.7 on page 154

unsigned long

INTEGER*4

See note 2

unsigned short

INTEGER*4

See note 1

unsigned small

INTEGER*2

See note 1

Notes

  1. For these IDL data types, the DIGITAL FORTRAN data type is chosen because it can represent all possible values of the IDL type. Note that, in each case, there are values of the DIGITAL FORTRAN type, which cannot be represented in the IDL type. You must not attempt to pass such values in parameters. The RPC runtime code does not perform range checking.

  2. Because some values that can be represented in an IDL data type cannot be represented correctly in the DIGITAL FORTRAN data type, the IDL compiler issues a warning.

  3. You must compile DIGITAL FORTRAN code that uses this data type and specify the cc-cmd 'command_line' compiler option.

  4. Status code mapping will occur where necessary.

  5. For any structure type in the IDL file that is not defined through a typedef statement, the IDL compiler generates the name of the DIGITAL FORTRAN structure. To determine what name was generated, look at filename.for.

  6. The semantics of conformant structures cannot be represented in DIGITAL FORTRAN. In the definition of such a structure in filename.for, a placeholder for the conformant array field is specified as a one-dimensional array with one element. If the first lower bound of the conformant array is fixed, this value is used as the lower and upper bounds of the placeholder. If the first lower bound of the array is not fixed and if the first upper bound of the conformant array is fixed, the upper bound is used as the lower and upper bounds of the placeholder. Otherwise, the lower and upper bounds of the placeholder are zero.

  7. Note that IDL encapsulated union types and nonencapsulated union types are represented as DIGITAL FORTRAN structures containing unions.

  8. IDL array types are converted to arrays of a nonarray base type.

  9. Arrays that do not have a specified lower bound have a lower bound of zero. Consider the following two statements in an IDL file:

    double d[10][20];
    short e[2..4][3..6];
    

    The statements map into the following DIGITAL FORTRAN constructs.

    REAL*8 D(0:9,0:19)
    INTEGER*2 E(2:4,3:6)
    

  10. The size of the pointer depends on the platform. It is INTEGER*8 for Tru64 UNIX systems.

12.4.5 Operations

Operations can pass parameters and return function results. This section explains these two topics.

12.4.5.1 Parameter Passing by Reference

The following rules explain the mapping between IDL parameters and DIGITAL FORTRAN parameters.

12.4.5.2 Function Results

The only possible function result types in DIGITAL FORTRAN are scalars and CHARACTER*n. The mappings from IDL to DIGITAL FORTRAN never produce CHARACTER*n, where n is greater than 1.

IDL hyper integers are not scalars in terms of function results, but IDL pointers are treated as scalars because they are mapped to INTEGER*8.

For an operation that has a result type that is not allowed by DIGITAL FORTRAN, the stubs treat the operation result as an extra [out] parameter added to the end of the parameter list.

If the type of an operation is not void, you must state the type of the function result in DIGITAL FORTRAN.

12.4.6 Include Files

Usually, a DIGITAL FORTRAN routine that is part of an RPC client or manager for the interface defined in filename.idl must include the following files:

Program units print_pay.for and manager.for (containing subroutine subprogram CALCULATE_PAY) in the example of a distributed payroll application do not include nbase.for because the units contain none of the IDL data types. Otherwise, the program units would include nbase.for. Furthermore, these units could safely include nbase.for even though it is unnecessary in the example.

12.4.7 The nbase.for File

The file /usr/include/dce/nbase.for declares standard data types used in mapping IDL to DIGITAL FORTRAN. The declarations are shown in Table 12-4.

Table 12-4: Standard Declarations

IDL Data Type FORTRAN Declaration
hyper

STRUCTURE /IDL_HYPER_INT/
INTEGER*4 LOW
INTEGER*4 HIGH
END STRUCTURE
unsigned hyper

STRUCTURE /IDL_UHYPER_INT/
INTEGER*4 LOW
INTEGER*4 HIGH
END STRUCTURE
handle_t

STRUCTURE /HANDLE_T/
INTEGER*4 OPAQUE_HANDLE
END STRUCTURE
ISO_MULTI_LINGUAL

STRUCTURE /ISO_MULTI_LINGUAL/
BYTE ROW
BYTE COLUMN
END STRUCTURE
ISO_UCS

STRUCTURE /ISO_UCS/
BYTE GROUP
BYTE PLANE
BYTE ROW
BYTE_COLUMN
END STRUCTURE

NOTE: For IDL data type handle_t, the size of pointers is platform specific: on OpenVMS systems, pointers are INTEGER*4 and on Tru64 UNIX systems, pointers are INTEGER*8.

12.4.8 IDL Attributes

This section describes IDL attributes that apply to RPC applications containing DIGITAL FORTRAN modules.

12.4.8.1 Binding Handle Callout

The Binding Handle Callout feature lets you specify a routine that is automatically called from an IDL-generated client stub routine, in order to modify the binding handle.

You can typically use this feature to augment the binding handle with security context, for example, so that authenticated RPC calls are used between client and server.

This feature is particularly targeted at clients which use automatic binding via the auto_handle ACF attribute. For automatic binding, it is the client stub rather than the client application code which obtains a server binding handle. The binding callout feature lets you modify binding handles obtained by the client stub. Without this feature, you cannot modify the binding handles before the client stub attempts to initiate a remote procedure call to the selected server.

12.4.8.2 ACF file

To select the binding handle callout feature, create an ACF file for the interface (if necessary) and place the binding_callout attribute on the interface. An example follows:

[auto_handle, binding_callout(my_bh_callout)] interface bindcall
{
}

The binding_callout attribute has the following general form:

   [binding_callout(identifier)]

You can specify the binding_callout only once per interface; it applies to all operations in that interface.

12.4.8.3 Generated header file

The IDL-generated header file for the interface contains a function prototype for the binding callout routine. In the previous example, bindcall.h contains a declaration similar to the following declaration:

    void my_bh_callout(
        rpc_binding_handle_t *p_binding,
        rpc_if_handle_t interface_handle,
        error_status_t *p_st
    );

12.4.8.4 Generated client stub

Each client stub routine in the IDL-generated client stub module calls the binding callout routine just before initiating the remote procedure call to the server. In the previous example, each client stub routine contains a call to my_bh_callout and passes the three arguments that are described in the following section.

12.4.8.5 Binding callout routine

The arguments to the binding callout routine are:

12.4.8.6 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 will 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, it will execute 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.

12.4.8.7 Predefined binding callout routine

There is one predefined binding callout routine in the DCE library which 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:

12.4.8.8 The transmit_as Attribute

The presented type must be expressible in DIGITAL FORTRAN. Because addresses are involved, the routines used for data conversion cannot be written in DIGITAL FORTRAN.

12.4.8.9 The string Attribute

A DIGITAL FORTRAN data item corresponding to an IDL string contains the number of characters specified for the IDL string. Because IDL strings are usually terminated with a null byte, the following transmission rules apply:

An IDL operation can have a conformant string parameter. Such a parameter is presented to DIGITAL FORTRAN as type CHARACTER*(*). If the base type of the string consists of w bytes and the string consists of n characters, then the parameter size is n*w. The maximum parameter size supported is 65535.

A conformant string field of a structure will have type CHARACTER*w, where w is the number of bytes in the base type of the string.

In all other cases where a string is not the target of a pointer, the IDL file specifies the string. Such a string is presented to DIGITAL FORTRAN as CHARACTER*s, where s is the product of the string length and the number of bytes in the base type of the string. Furthermore, s must be between 1 and 65535 inclusive.

12.4.8.10 The context_handle Attribute

A context handle rundown routine cannot be written in DIGITAL FORTRAN because the routine must handle address information.

12.4.8.11 The Array Attributes on [ref] Pointer Parameters

A [ref] pointer parameter that has array attributes attached to it is presented to DIGITAL FORTRAN as the equivalent array.

12.4.9 ACF Attributes

The following items can occur in an Attribute Configuration File (ACF). They require special consideration when you are using DIGITAL FORTRAN.

12.4.9.1 The implicit_handle ACF Attribute

You must supply a COMMON block whose name is the name given in the implicit handle clause. This COMMON block must contain the binding handle as its only data item.

For example, suppose an ACF contains the following interface attribute:

[implicit_handle(handle_t i_h)]

Then, any DIGITAL FORTRAN routine that calls an operation which uses the implicit binding must include statements with the following form:

RECORD /HANDLE_T/ BINDING_HANDLE
COMMON /I_H/      BINDING_HANDLE

12.4.9.2 The represent_as ACF Attribute

The local type must be expressible in DIGITAL FORTRAN.

Because addresses are involved, you cannot write the data conversion routines in DIGITAL FORTRAN.

A type name in a represent_as attribute that does not occur in the interface definition and is not an IDL base type is assumed to be a STRUCTURE type.

Suppose that the represent_as type is not an IDL base type or a type defined in your IDL source. Then, you must supply a .h file whose unextended name is given in an include statement in the ACF. (An unextended name is a filename without the file extension that follows the final dot (.) in the name. For example, the unextended filename for file example.h is example.) This file must include a definition of the local type in C syntax. You will need a filename.for file containing a DIGITAL FORTRAN definition of the local type. Entegrity recommends that you assign this file the same unextended name.


[Previous] [Next] [Contents] [Index]


To make comments or ask for help, contact support@entegrity.com.

Copyright © 2001 Entegrity Solutions Corporation & its subsidiaries.

Copyright © 1998-2001 Compaq Computer Corporation.

All rights reserved.