|
Digital DCE for OpenVMS VAX and OpenVMS
Alpha Product Guide
18.2.3 Compiling the Interface with the IDL Compiler
To compile an RPC interface, you must invoke the IDL compiler. To
compile an RPC interface for a VAX FORTRAN application, you must select
the following IDL options:
- Option -lang fortran (universal syntax) or the qualifier
/LANGUAGE=FORTRAN (OpenVMS DCL syntax). This option specifies FORTRAN
as the source code language.
- Option -standard extended (universal syntax) or the
qualifier /STANDARD=EXTENDED (OpenVMS DCL syntax). This option enables
features beyond those available in OSF DCE.
The following example commands illustrate how to invoke the IDL
compiler using the universal and DCL interfaces, respectively, to
compile the sample VAX FORTRAN application interface:
$ idl payroll.idl -lang fortran -standard extended
$ IDL/LANGUAGE=FORTRAN/STANDARD=EXTENDED
PAYROLL.IDL
|
As a result of this command, the IDL compiler generates the files
listed in Table 18-2.
Table 18-2 Example Files Created by IDL
| Filename |
File Description |
|
PAYROLL_CSTUB.OBJ
|
The stub file generated by the IDL compiler for the client side of the
application.
|
|
PAYROLL_SSTUB.OBJ
|
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 by PAYROLL.COM 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 VAX 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.
18.2.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 MASSACHUSETTS.
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 DCL commands. After you enter the LINK
command, press <CTRL/Z>.
$ FORTRAN PRINT_PAY.FOR
$ LINK PRINT_PAY, PAYROLL_CSTUB, DCE:DCE/OPT, DCE:DCE_VAXC/OPT
|
Instead of using these two commands directly to build the client part
of the application, you can invoke procedure PAYROLL.COM to build the
entire application. See Section 18.2.8 for information about building and
running this example.
This program reads its data from VAX FORTRAN logical unit 4. A DCL
command in procedure PAYROLL.COM defines the logical unit.
18.2.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.
This file is shown next. Both SERVER.C and PAYROLL.COM (shown in this
section and in Section 18.2.8, respectively) contain the literal
FORTRAN_payroll_mynode. Do not substitute a node name for
mynode. The code in SERVER.C always exports its bindings using
the entry name ".:/FORTRAN_payroll_mynode".
/* 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));
}
|
18.2.6 The Server Application Code for the Interface (MANAGER.FOR)
The server application code, written in VAX FORTRAN, is declared in
file PAYROLL.IDL as calculate_pay(). The file MANAGER.FOR
provides some additional application code for the server and it
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 MASSACHUSETTS.
C The structure of a time card is described in included 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 of GRADE,
C 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.EXE, which at runtime responds to remote
procedure calls from a client that supports the payroll interface, use
the following DCL commands. After you enter the LINK command, press
<CTRL/Z>.
$ CC SERVER
$ FORTRAN MANAGER
$ LINK SERVER, MANAGER, PAYROLL_SSTUB, DCE:DCE/OPT, DCE:DCE_VAXC/OPT
|
Instead of using these commands directly to build the server part of
the application, you can invoke procedure PAYROLL.COM to build the
entire application (see Section 18.2.8).
18.2.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 18.2.4. 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 calculate the gross pay.
CALL CALCULATE_PAY (CARDS, PAY)
|
When you invoke procedure PAYROLL.COM (shown in Section 18.2.8), it
displays a message 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.
18.2.8 Building and Running the Example (PAYROLL.COM)
You can build, run, or both build and run the payroll example by using
command file PAYROLL.COM.
Its contents follow.
$!
$! This is file PAYROLL.COM to build, run, or both build and run
$! the distributed payroll application.
$!
$! 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.
$!
$!
$! @PAYROLL is the default -- to build and run.
$! @PAYROLL BUILD does only the build.
$! @PAYROLL RUN does only a sample run.
$!
$ SAY := WRITE SYS$OUTPUT
$ IF P1 .eqs. "RUN" then goto DO_RUN
$!
$! Build the application.
$ SAY "Building..."
$
$! Enable the universal IDL command interface
$ idl := $sys$system:dce$idl.exe
$
$! Compile the interface definition
$! -keep all is used to keep the IDL output for training purposes
$ idl PAYROLL.IDL -keep all -trace all -trace log_manager -lang fortran -
-standard extended
$
$! Compile the client application files
$ FORTRAN PRINT_PAY
$
$! Link the client application
$ LINK PRINT_PAY,PAYROLL_CSTUB, DCE:DCE/OPT, DCE:DCE_VAXC/OPT
$
$! Compile the server application files
$ CC SERVER
$ FORTRAN MANAGER
$
$! Link the server application
$ LINK SERVER,MANAGER,PAYROLL_SSTUB,DCE:DCE/OPT,DCE:DCE_VAXC/OPT
$ IF P1 .eqs. "BUILD" then exit
$
$DO_RUN:
$! Run the application.
$ SAY "Activating server image..."
$ DEFINE/NOLOG RPC_DEFAULT_ENTRY ".:/FORTRAN_payroll_mynode"
$ SPAWN/NOWAIT/INPUT=NL:/OUTPUT=SERVER.LOG/PROCESS=FORTRAN_SERVER -
RUN SERVER
$ WAIT 00:00:10 ! Allow 10 seconds for the server to start.
$ DEFINE/NOLOG FOR004 PAYROLL.DAT
$ SAY "Activating client image..."
$ RUN PRINT_PAY
$ SAY "Deleting server process..."
$ STOP FORTRAN_SERVER
$ SAY "End of sample application"
|
If you prefer to use OpenVMS DCL syntax for the command to the IDL
compiler, then one way to modify file PAYROLL.COM follows.
Consider these seven lines:
$! Enable the universal IDL command interface
$ idl := $sys$system:dce$idl.exe
$
$! Compile the interface definition
$! -keep all is used to keep the IDL output for training purposes
$ idl PAYROLL.IDL -keep all -trace all -trace log_manager -lang fortran -
-standard extended
|
Change the second, third, sixth, and seventh lines to comments by
adding a "$!" at the beginning of each line (or delete all seven
lines). Then, add the following three lines before the two lines:
$
$! Compile the client application files
$! Use OpenVMS DCL syntax for the command to the IDL compiler.
$ IDL/KEEP=ALL/TRACE=(EVENTS=ALL,LOG_MANAGER)/LANGUAGE=FORTRAN -
/STANDARD=EXTENDED PAYROLL.IDL
|
This modification works only if you do not otherwise have the symbol
IDL defined.
18.2.9 Example Output
The output from building and running the sample application looks like
this:
Building...
Operation calculate_pay has no binding handle parameter; [auto_handle] assumed
Activating server image...
%DCL-S-SPAWNED, process FORTRAN_SERVER spawned
Activating client image...
Jerry Harrison 372
Tony Hardiman 294
Mary Flynn 321
FORTRAN STOP
Deleting server process...
End of sample application
|
The next time you need to run this application, enter this command:
The output from building this application includes files PRINT_PAY.EXE
(client) and SERVER.EXE (server). You can use these executable programs
in separate client and server processes.
18.3 Remote Procedure Calls Using FORTRAN --- Reference
Section 18.2 contains a comprehensive example that introduces creating
distributed applications with VAX FORTRAN program units. This section
goes beyond the example to provide reference information and explain
general concepts about creating these distributed applications.
18.3.1 The FORTRAN Compiler Option
If you are generating stubs and include files for application code
written in VAX FORTRAN, you must specify it as the language of choice
when you compile the application's IDL file. To specify the VAX FORTRAN
language using the universal syntax, specify -lang fortran;
the default value is -lang c. To specify the VAX FORTRAN
language using DCL syntax, specify /LANGUAGE=FORTRAN; the default value
is /LANGUAGE=CC.
In the remainder of this chapter, the phrase "FORTRAN option" refers to
the IDL command that specifies VAX FORTRAN. Examples of the IDL command
and specification are presented in Section 18.2.3.
Any client or server stub files that the FORTRAN option generates use
the VAX FORTRAN linkage conventions. This means that all parameters are
passed by reference (see Section 18.3.5.1 for more information). In
addition, all identifiers are converted to uppercase.
The FORTRAN option generates the file filename.FOR, which
includes VAX 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 VAX 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 VAX FORTRAN stubs
for any interface that imports this interface.
Consider the header option whose syntax is -header (universal)
or /HEADER= (OpenVMS DCL). 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.
- If you specify a directory name in the header option, the compiler
places the files in that directory. Otherwise, it places the files in
the current default directory.
- If you specify a filename without an extension in the header
option, the compiler uses that filename with the extensions .FOR and
.FOR_H.
- If you specify a filename with an extension in the header option,
the compiler uses that file extension instead of .FOR_H; however, the
compiler does not change the extension of the .FOR file.
18.3.2 Restrictions on the Use of FORTRAN
This section discusses restrictions on distributed applications written
in VAX FORTRAN that make remote procedure calls. These restrictions are
on interfaces and stubs, and on runtime operations.
- If an interface contains any arrays that have more than seven
dimensions, the IDL compiler cannot produce output that is compatible
with VAX FORTRAN.
- If an interface contains two identifiers that differ only in the
case of their characters, the IDL compiler may not be able to build
stubs.
- The stubs generated for VAX FORTRAN cannot call operations that use
pipes.
- If the transmit_as or represent_as attributes
have been applied to a character array type used to define the
parameters of an operation, then VAX FORTRAN cannot call that operation.
- If the transmit_as or represent_as attributes
have been applied to an array type that, in turn, is the base type of
an array type used to define the parameters of an operation, then VAX
FORTRAN cannot call that operation.
- If the v1_array attribute has been applied to any
parameter of an operation, then VAX FORTRAN cannot call that operation.
- VAX FORTRAN does not allow the concurrent execution of two or more
threads.
In particular, if a server implements remote operations in VAX FORTRAN,
it must restrict the number of threads of server execution to 1. The
following statement in file SERVER.C (shown in Section 18.2.5) specifies
this restriction:
rpc_server_listen((int)1, &st);
|
18.3.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 (?).
18.3.4 Type Mapping
An IDL type that is a synonym for another type is presented to VAX
FORTRAN as the type for which the synonym is defined. For example,
suppose that the IDL file contains the following statement:
Then, all instances of IDL type \*Cbar) are presented to VAX FORTRAN as
of type foo.
Table 18-3 describes the mappings from IDL types to VAX FORTRAN
types:
Table 18-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 description of NBASE.FOR in this chapter
|
|
hyper
|
IDL_HYPER_INT
|
See description of NBASE.FOR
|
|
ISO_MULTI_LINGUAL
|
ISO_MULTI_LINGUAL
|
See description of NBASE.FOR
|
|
ISO_UCS
|
ISO_UCS
|
See description of NBASE.FOR
|
|
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 description of NBASE.FOR
|
|
unsigned long
|
INTEGER*4
|
See note 2
|
|
unsigned short
|
INTEGER*4
|
See note 1
|
|
unsigned small
|
INTEGER*2
|
See note 1
|
Notes
- For these IDL data types, the VAX 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 VAX 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.
- Because some values that can be represented in an IDL data type
cannot be represented correctly in the VAX FORTRAN data type, the IDL
compiler issues a warning.
- You must compile VAX FORTRAN code that uses this data type and
specify the /G_FLOAT compiler option.
- Status code mapping will occur where necessary.
- For any structure type in the IDL file that is not defined through
a typedef statement, the IDL compiler generates the name of the VAX
FORTRAN structure. To determine what name was generated, look at
filename .FOR.
- The semantics of conformant structures cannot be represented in VAX
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.
- Note that IDL encapsulated union types and nonencapsulated union
types are represented as VAX FORTRAN structures containing unions.
- IDL array types are converted to arrays of a nonarray base type.
- Arrays that do not have a specified lower bound have a lower bound
of zero. Consider the following two statements in an IDL file:
|