Previous | Contents | Index |
To make global data available across Compaq Fortran and Compaq Fortran 77 procedures, use common blocks.
Common blocks are supported by both Compaq Fortran 77 and Compaq Fortran, but modules are not supported by Compaq Fortran 77. Some suggestions about using common blocks follow:
Compaq Fortran and Compaq Fortran 77 share the same run-time system, so you can perform I/O to the same unit number with Compaq Fortran and Compaq Fortran 77 procedures. For instance, a Compaq Fortran main program can open the file, a Compaq Fortran 77 function can issue READ or WRITE statements to the same unit, and the Compaq Fortran main program can close the file.
Before creating a mixed-language program that contains procedures written in Compaq Fortran and C, you need to know how to:
On Linux Alpha systems, this section assumes the usage of the Compaq C
compiler (
ccc
command).
11.4.1 Compiling and Linking Files
Use the f90 or fort command (and not the cc or ccc command) to:
The f90 and fort commands pass the appropriate libraries to ld , including the Compaq Fortran libraries and libc .
You can use the cc and ccc commands with the -c option to compile C source files into object files.
For example, the following f90 command compiles and links the Compaq Fortran calling main program ex1.f90 and the called C function uopen_.c :
% f90 ex1.f90 uopen_.c |
You can use the cc or, on Linux systems, the ccc command to compile the C program into an object file before the f90 command:
% cc -c uopen_.c % f90 ex1.f90 uopen_.o |
The cc ( ccc ) and f90 ( fort ) commands:
When a C program calls a Compaq Fortran subprogram, specify the -nofor_main option on the f90 command line:
% cc -c cmain.c % f90 -nofor_main cmain.o fsub.f90 |
To view the preprocessor and compilers used and the libraries passed to ld , use the f90 command -v option.
When designing a program that will use Compaq Fortran and C, be aware of the following general rules and available Compaq Fortran capabilities:
You can use a function reference or a CALL statement to invoke a C function from a Compaq Fortran main or subprogram.
If a value will be returned, use a function reference:
C Function Declaration | Compaq Fortran Function Invocation |
---|---|
data-type calc_(
argument-list)
{ ... } ; |
EXTERNAL CALC
data-type :: CALC, variable-name ... variable-name=CALC( argument-list) ... |
If no value is returned, use a void return value and a CALL statement:
C Function Declaration | Compaq Fortran Subroutine Invocation |
---|---|
void calc_(
argument-list)
{ ... } ; |
EXTERNAL CALC
... CALL CALC( argument-list) |
A C main program or function can invoke a Compaq Fortran function or subroutine by using a function prototype declaration and invocation.
If a value is returned, use a FUNCTION declaration:
Compaq Fortran Declaration | C Invocation |
---|---|
FUNCTION CALC(
argument-list)
data-type :: CALC ... END FUNCTION CALC |
extern
data-type calc_(
argument-list)
data-type variable-name; variable-name=calc_( argument-list); ... |
If no value is returned, use a SUBROUTINE declaration and a void return value:
Compaq Fortran Declaration | C Invocation |
---|---|
SUBROUTINE CALC(
argument-list)
... END SUBROUTINE CALC |
extern void calc_(
argument-list)
calc_( argument-list); ... |
Both C and Compaq Fortran pass most function return data by value, but equivalent data types must be used. The following table lists equivalent function declarations in Compaq Fortran and C. See Table 11-4 for a complete list of data declarations.
C Function Declaration | Compaq Fortran Function Declaration |
---|---|
float rfort_() |
function rfort()
real (kind=4) :: rfort |
double dfort_() |
function dfort()
real (kind=8) :: dfort |
int ifort_() |
function ifort()
integer (kind=4) :: ifort |
Because there are no corresponding data types in C, you should avoid calling Compaq Fortran functions of type REAL (KIND=16), COMPLEX, and DOUBLE COMPLEX, unless for complex data you pass a struct of two float (or double ) C values (see Section 11.4.10).
The Compaq Fortran LOGICAL data types contain a zero if the value is false and a --1 if the value is true, which works with C conditional and if statements.
A character-valued Compaq Fortran function is equivalent to a C language routine with two extra initial arguments added by the Compaq Fortran compiler:
Compaq Fortran follows the argument-passing rules described in Section 11.1.4. These rules include:
Compaq Fortran lets you specify the lengths of its intrinsic numeric data types with the following:
The following declarations of the integer An are equivalent (unless you specified the appropriate f90 command option to override the default integer size):
INTEGER (KIND=4) :: A1 INTEGER (4) :: A2 INTEGER :: A3 INTEGER*4 :: A4 |
Character data in Compaq Fortran is passed and received by address, using an extra hidden-length argument to contain the string length. Dummy character arguments can use assumed-length syntax for accepting character data of varying length.
Consider the following Compaq Fortran subroutine declaration:
SUBROUTINE H (C) CHARACTER(LEN=*) C |
The equivalent C function declaration is:
void h_(char *c, int len); |
The Fortran subroutine can be called from C as follows:
. . . char *chars[15]; h_(chars, 15); |
The calling routine must pass the same number of arguments expected by the called routine. For each argument passed, the manner (mechanism) of passing the argument and the expected data type must match what is expected by the called routine. For instance, C usually passes data by value and Compaq Fortran typically passes argument data by reference (address and, when appropriate, length).
You must determine the appropriate data types in each language that are compatible. When you call a C routine from a Compaq Fortran main program, certain built-in functions may be useful to change the default passing mechanism, as discussed in Section 11.1.8.
If the calling routine cannot pass an argument to the called routine because of a language difference, you may need to rewrite the called routine. Another option is to create an interface jacket routine that handles the passing differences.
When a C program calls a Compaq Fortran subprogram, all arguments must be passed by reference because this is what the Compaq Fortran routine expects. To pass arguments by reference, the arguments must specify addresses rather than values. To pass constants or expressions, their contents must first be placed in variables; then the addresses of the variables are passed.
When you pass the address of the variable, the data types must correspond as shown in Table 11-4 for Compaq Tru64 UNIX systems:
Compaq Fortran Data Declaration | C Data Declaration |
---|---|
integer (kind=2) x | short int x; |
integer (kind=4) x | int x; |
integer (kind=8) x | long int x; __int64 x; |
logical x | unsigned x; |
real x | float x; |
double precision x | double x; |
real (kind=16) x | None 1 |
complex (kind=4) x | struct { float real; float imag } x; |
complex (kind=8) x | struct { double dreal; double dimag } x; |
complex (kind=16) x | struct { long double dreal; long double dimag } x; 1 |
character (len=5) x | char x[5] |
Be aware of the various sizes supported by Compaq Fortran for integer, logical, and real variables (see Chapter 9), and use the size consistent with that used in the C routine.
Compaq Fortran LOGICAL data types contain a zero if the value is false and a --1 if the value is true, which works with C language conditional and if statements.
When one of the arguments is character data, the Compaq Fortran compiler passes the address of the character data as an argument and adds the length of the character string to the end of the argument list (see Section 11.1.4).
When a C program calls a Compaq Fortran subprogram, the C program must explicitly specify these items in an argument list in the following order:
For example, consider the following Compaq Fortran function declaration that returns character data:
character(len=8) function ch() ch = 'ABCDEFG' //CHAR(0) return end |
The following C code invokes the Compaq Fortran function as ch_, explicitly passing the address and length of the character data arguments, as follows:
char s[8] ch_(&s[0],8); |
Any character string passed by Compaq Fortran is not
automatically null-terminated. To null-terminate a string from
Compaq Fortran, use the CHAR intrinsic function (as shown in the
previous example and described in the Compaq Fortran Language Reference Manual).
11.4.7 Example of Passing Integer Data to C Functions
Example 11-5 shows C code that declares the two functions hln_ and mgn_ . These functions display the arguments received. The C language function hln_ expects the argument by value, whereas mgn_ expects the argument by reference (address).
Example 11-5 C Functions Called by a Compaq Fortran Program |
---|
/* get integer by value from Fortran. File: pass_int_to_c.c */ void hln_(int i) { printf("99==%d\n",i); i = 100; } /* get integer by reference from Fortran */ void mgn_(int *i) { printf("99==%d\n",*i); *i = 101; } |
Example 11-6 shows the Compaq Fortran (main program) code that calls the two C functions mgn_ and hln_ .
Example 11-6 Calling C Functions and Passing Integer Arguments |
---|
! Using %REF and %VAL to pass argument to C. File: pass_int_to_cfuncs.f90 integer :: i i = 99 call hln(%VAL(i)) ! pass by value print *,"99==",i call mgn(%REF(i)) ! pass by reference - %REF is optional in this case print *,"101==",i i = 99 call mgn(i) ! pass by reference print *,"101==",i |
The files (shown in Example 11-5 and Example 11-6) might be compiled, linked, and run as follows:
% cc -c pass_int_to_c.c % f90 -o pass_int_to_c pass_int_to_cfuncs.f90 pass_int_to_c.o % pass_int_to_c 99==99 99== 99 99==99 101== 101 99==99 101== 101 |
The following examples show a Compaq Fortran program that calls a C function that serves as an interface (jacket) routine to the setenv library routine (described in setenv(3)).
The Compaq Fortran program is named test_setenv.f .
The C program that contains the setenv_ interface function is named fort_setenv.c .
The Compaq Fortran program performs the following tasks:
Example 11-7 shows the Compaq Fortran program test_setenv.f .
Example 11-7 Compaq Fortran Program Calling a C Function |
---|
! test_setenv.f character(len=50) :: ename, evalue integer :: overwrite, setenv, ret ! Use 3f routine getenv to return PRINTER environment variable value call getenv('PRINTER',evalue) ! Now look at current value write(6,*) 'Previous env. variable value of PRINTER is: ', evalue ! Use setenv C function. Overwrite flag = non-zero means ! overwrite any existing environment variable. ! ! Returns -1 if there was an error in setting the environment variable ename = 'PRINTER' evalue = 'lps40' overwrite = 1 ret = setenv(ename,evalue,overwrite) if (ret < 0) write (6,*) 'Error setting env. variable' ! Now look at current value evalue = ' ' call getenv('PRINTER',evalue) write(6,*) 'New env. variable value of PRINTER is: ', evalue end |
Example 11-8 shows the C program fort_setenv.c .
Example 11-8 C Interface Function Called by Compaq Fortran |
---|
/* fort_setenv.c */ #include <stdlib.h> int setenv_(char *ename,char *evalue,int *overwrite,int ilen1,int ilen2) { int setenv(), lnblnk_(), i1, i2, ow, rc; char *p1, *p2; /* Get string length of each input parameter */ i1 = lnblnk_(ename,ilen1); i2 = lnblnk_(evalue,ilen2); /* Allocate temporary storage */ p1 = malloc((unsigned) i1+1); if( p1 == NULL ) return(-1); p2 = malloc((unsigned) i2+1); if( p2 == NULL ) { free(p1); return(-1); } /* Copy strings, and NUL terminate */ strncpy(p1,ename,i1); p1[i1] = '\0'; strncpy(p2,evalue,i2); p2[i2] = '\0'; ow = *overwrite; /* Call the setenv library routine to set the environment variable */ rc = setenv(p1, p2, ow); free(p1); free(p2); return(rc); } |
The setenv_ function (shown in Example 11-8) sets the environment variable PRINTER to the value lps40 (passed as arguments from the Compaq Fortran calling program) by calling the setenv library routine with the overwrite flag set to 1.
The C function (shown in Example 11-8) uses the passed length to find the last nonblank character and uses the string up to that character. The C variables ilen1 and ilen2 receive the hidden length of the character strings ename and evalue respectively. The C function allocates storage, including an extra byte for the null-terminator to each string. The extra byte is used as part of an argument when calling the setenv library routine.
The following Compaq Fortran code in Example 11-7 calls the setenv_ C function:
ret=setenv(ename,evalue,overwrite) |
This function invocation passes the following arguments to the C function setenv_ :
Compaq Fortran Variable | Purpose | Data Type | How Passed |
---|---|---|---|
ename | Environment variable name | character | by reference, not null-terminated |
evalue | Environment variable string | character | by reference, not null-terminated |
overwrite | Overwrite flag for setenv | integer | by reference |
not declared | Hidden length of ename | integer | by value |
not declared | Hidden length of evalue | integer | by value |
Data passed from Compaq Fortran to C is passed by reference. When passing character data from Compaq Fortran to C, the following rules apply:
The C function (in Example 11-8) is declared as setenv_ and accepts the Compaq Fortran arguments with the following function declaration:
int setenv_(ename,evalue,overwrite,ilen1,ilen2) char *ename, *evalue; int *overwrite; int ilen1, ilen2; |
The status returned from the C function to the calling Compaq Fortran program is an integer passed by value. (The C function obtains this value from setenv library routine.)
To create the executable program, the files might be compiled with the following commands:
% cc -c fort_setenv.c % f90 test_setenv.f fort_setenv.o |
When executed, a.out displays:
% a.out Previous env. variable value of PRINTER is: lpr New env. variable value of PRINTER is: lps40 |
Previous | Next | Contents | Index |