Compaq Fortran
User Manual for
Tru64 UNIX and Linux Alpha Systems


Previous Contents Index

11.3.2 Using Data Items in Common Blocks

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:

11.3.3 I/O to the Same Unit Number

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.

For More Information:

11.4 Calling Between Compaq Fortran and C

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:

  1. Apply cpp to the uopen_.c file (done by cc and ccc )
  2. Compile uopen_.c into the object file uopen_.o (done by cc and ccc )
  3. Compile ex1.f90 into an object file (done by f90 and fort )
  4. Link both resulting object files to create the file a.out file (done by ld )

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.

For More Information:

11.4.2 Procedures and External Names

When designing a program that will use Compaq Fortran and C, be aware of the following general rules and available Compaq Fortran capabilities:

11.4.3 Invoking a C Function from Compaq Fortran

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)

11.4.4 Invoking a Compaq Fortran Function or Subroutine from C

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);
...

11.4.5 Equivalent Data Types for Function Return Values

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:

For More Information:

11.4.6 Argument Association and Equivalent Data Types

Compaq Fortran follows the argument-passing rules described in Section 11.1.4. These rules include:

11.4.6.1 Compaq Fortran Intrinsic Data Types

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); 

For More Information:

11.4.6.2 Equivalent Compaq Fortran and C Data Types

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:

Table 11-4 Compaq Fortran and C Data Types
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]


1The equivalent C declaration is long double (may not support X_floating).

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:

  1. For a character function, the address of the character function result and the length of the character function result
  2. For normal arguments, the addresses of arguments or functions
  3. The lengths of any character string arguments, specified as integer variables (passed in the same order as the arguments)

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 

11.4.8 Example of Passing Character Data Between Compaq Fortran and C

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:

  1. Calls the getenv function (a Section 3f library routine) and displays the current value of the environment variable PRINTER (described in getenv(3f))
  2. Calls the setenv_ interface function to set the new value for the environment variable PRINTER
  3. Calls the getenv function again and displays the new value of the environment variable PRINTER

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