Compaq Fortran
User Manual for
OpenVMS Alpha Systems


Previous Contents Index

10.8 Calling Between Compaq Fortran 77 and Compaq Fortran

On OpenVMS Alpha systems, you can call a Compaq Fortran 77 subprogram from Compaq Fortran or call a Compaq Fortran subprogram from Compaq Fortran 77 (with very few exceptions). A Compaq Fortran 77 procedure and a Compaq Fortran procedure can also perform I/O to the same unit number.

10.8.1 Argument Passing and Function Return Values

The recommended rules for passing arguments and function return values between Compaq Fortran 77 and Compaq Fortran procedures are as follows:

Example 10-6 and Example 10-7 show passing an array from a Compaq Fortran program to a Compaq Fortran 77 subroutine that prints its value.

Example 10-6 shows the Compaq Fortran program (file ARRAY_TO_F77.F90). It passes the same argument as a target and a pointer. In both cases, it is received by reference by the Compaq Fortran 77 subroutine as a target (regular) argument. The interface block in Example 10-6 is not needed, but does allow data type checking.

Example 10-6 Compaq Fortran Program Calling a Compaq Fortran 77 Subroutine

 ! Pass arrays to f77 routine. File: ARRAY_TO_F77.F90 
 
 ! This interface block is not required, but must agree 
 ! with actual procedure. It can be used for type checking. 
 
 INTERFACE                    ! Procedure interface block 
   SUBROUTINE MEG(A) 
   INTEGER :: A(3) 
   END SUBROUTINE 
 END INTERFACE 
 
 INTEGER, TARGET :: X(3) 
 INTEGER, POINTER :: XP(:) 
 
 X = (/ 1,2,3 /) 
 XP => X                         
 
 CALL MEG(X)                  ! Call f77 implicit interface subroutine twice. 
 CALL MEG(XP)                
 END 

Example 10-7 shows the Compaq Fortran 77 program called by the Compaq Fortran program (file ARRAY_F77.FOR).

Example 10-7 Compaq Fortran 77 Subroutine Called by a Compaq Fortran Program

      ! Get array argument from F90. File: ARRAY_F77.FOR 
 
       SUBROUTINE MEG(A) 
       INTEGER A(3) 
       PRINT *,A 
       END 

These files (shown in Example 10-6 and Example 10-7) might be compiled, linked, and run as follows:


$ FORTRAN ARRAY_TO_F77.F90
$ FORTRAN /OLD_F77 ARRAY_F77.FOR
$ LINK/EXECUTABLE=ARRAY_TO_F77 ARRAY_TO_F77, ARRAY_F77
$ RUN ARRAY_TO_F77
           1           2           3 
           1           2           3 

In Example 10-6, because array A is not defined as a pointer in the interface block, the Compaq Fortran pointer variable XP is passed as target data by reference (address of the target data).

However, if the interface to the dummy argument had the POINTER attribute, the variable XP would be passed by descriptor. This descriptor would not work with the Compaq Fortran 77 program shown in Example 10-7.

For More Information:

10.8.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 and Compaq Fortran 77, but modules are not supported by Compaq Fortran 77. Some suggestions about using common blocks follow:

10.8.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 by 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:

10.9 Calling Between Compaq Fortran and Compaq C

Before creating a mixed-language program that contains procedures written in Compaq Fortran and C, you need to know how to:

10.9.1 Compiling and Linking Files

Use the FORTRAN command to compile Compaq Fortran source files and CC to compile C source files. Link the object files using a LINK command.

For example, the following FORTRAN command compiles the Compaq Fortran main program EX1.F90 and the called C function UPEN.C:


$ FORTRAN EX1.F90 
$ CC UPEN.C

The following LINK command creates the executable program:


$ LINK EX1, UPEN

10.9.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:

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

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

10.9.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 a sample of equivalent function declarations in Compaq Fortran and C. See Table 10-8 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 COMPLEX and DOUBLE COMPLEX, unless you pass a struct of two float (or double float) C values (see Section 10.9.9).

The floating-point format used in memory is determined by the /FLOAT qualifier for both the FORTRAN and CC commands. When floating-point data is passed as an argument or is globally available, the same floating-point format must be used in memory by both the C and Compaq Fortran parts of your program.

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.

For More Information:

10.9.6 Argument Association and Equivalent Data Types

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

10.9.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 FORTRAN command qualifier):


INTEGER (KIND=4) :: A1 
INTEGER (4)      :: A2 
INTEGER          :: A3 
INTEGER*4        :: A4 

Character data in Compaq Fortran is passed and received by character descriptor. Dummy character arguments can use assumed-length for accepting character data of varying length.

For More Information:

On Compaq Fortran intrinsic data types, see Chapter 8.

10.9.6.2 Equivalent Compaq Fortran and C Data Types

The calling routine must pass the same number of arguments expected by the called routine. Also, 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.

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 Fortran cDEC$ ATTRIBUTES directives may be useful to change the default passing mechanism (such as cDEC$ ATTRIBUTES C) as discussed in Section 10.3.2.

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 10-8 for OpenVMS Alpha systems:

Table 10-8 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 __int64 x;
logical x unsigned x;
real x float x;
double precision x double x;
real (kind=16) x long double x; 1
complex (kind=4) x struct { float real, float imag; } x;
complex (kind=8) x struct { double dreal, double dimag } x;
character(len=5) char x[5]


1Compaq C interprets this as either a 128-bit IEEE X_FLOAT or a 64-bit floating-point number, depending on the value specified in the CC /L_DOUBLE-SIZE qualifier. The default is /L_DOUBLE-SIZE=128.

Be aware of the various sizes supported by Compaq Fortran for integer, logical, and real variables (see Chapter 8), 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.

The floating-point format used in memory is determined by the /FLOAT qualifier for both the FORTRAN and CC commands. When floating-point data is passed as an argument or is globally available, the same floating-point format must be used in memory both by the C and Compaq Fortran parts of your program.

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 (described in the Compaq Fortran Language Reference Manual).

10.9.7 Example of Passing Integer Data to C Functions

Example 10-8 shows C code that declares the two functions HLN and MGN. These functions display the arguments received. The function HLN expects the argument by value, whereas MGN expects the argument by reference (address).

Example 10-8 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 10-9 shows the Compaq Fortran (main program) code that calls the two C functions HLN and MGN.

Example 10-9 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 
  PRINT *,"101==",I 
  I = 99 
  CALL MGN(I)             ! pass by reference 
  PRINT *,"101==",I 
  END 

The files (shown in Example 10-8 and Example 10-9) might be compiled, linked, and run as follows:


$ FORTRAN PASS_INT_TO_CFUNCS.F90 
$ CC PASS_INT_TO_C.C
$ LINK/EXECUTABLE=PASS_INT PASS_INT_TO_CFUNCS, PASS_INT_TO_C
$ RUN PASS_INT
99==99 
99==          99 
99==99 
101==         101 
99==99 
101==         101 

10.9.8 Example of Passing Complex Data to C Functions

Example 10-10 shows Compaq Fortran code that passes a COMPLEX (KIND=4) value (1.0,0.0) by immediate value to subroutine foo. To pass COMPLEX arguments by value, the compiler passes the real and imaginary parts of the argument as two REAL arguments by immediate value.

Example 10-10 Calling C Functions and Passing Complex Arguments

 
  ! Using !DEC$ATTRIBUTES to pass COMPLEX argument by value to F90 or C. 
  ! File: cv_main.f90  
 
  interface 
     subroutine foo(cplx) 
       !DEC$ATTRIBUTES C :: foo 
          complex cplx 
     end subroutine 
  end interface 
 
    complex(kind=4) c 
    c = (1.0,0.0) 
    call foo(c)             ! pass by value 
 
  end 

If subroutine foo were written in Compaq Fortran, it might look similar to the following example. In this version of subroutine foo, the COMPLEX parameter is received by immediate value. To accomplish this, the compiler accepts two REAL parameters by immediate value and stores them into the real and imaginary parts, respectively, of the COMPLEX parameter cplx.


 
  ! File: cv_sub.f90  
 
     subroutine foo(cplx) 
       !DEC$ATTRIBUTES C :: foo 
       complex cplx 
 
       print *, 'The value of the complex number is ', cplx 
 
     end subroutine 

If subroutine foo were written in C, it might look similar to the following example in which the complex number is explicitly specified as two arguments of type float.


  /* File: cv_sub.c */ 
 
  #include <stdio.h> 
 
  typedef struct {float c1; float c2;} complex; 
 
    void foo(complex c) 
  { 
      printf("The value of the complex number is (%f,%f)\n", c1, c2); 
  } 

The main routine (shown in Example 10-10) might be compiled and linked to the object file created by the compilation of the Compaq Fortran subroutine and then run as follows:


$ FORTRAN CV_MAIN.F90 
$ FORTRAN CV_SUB.F90
$ LINK/EXECUTABLE=CV.EXE CV_MAIN.OBJ, CV_SUB.OBJ 
$ RUN CV
1.000000,0.0000000E+00 

The main routine might also be compiled and linked to the object file created by the compilation of the C subroutine and then run as follows:


$ CC CV_SUB.C
$ LINK/EXECUTABLE=CV2.EXE CV_MAIN.OBJ CV_SUB.OBJ 
$ RUN CV2
1.000000,0.000000 


Previous Next Contents Index