Most C-Fortran interfaces must agree in all of these aspects:
Function/subroutine: definition and call
Data types: compatibility of types
Arguments: passing by reference or value
Arguments: order
Procedure name: uppercase and lowercase and trailing underscore (_)
Libraries: telling the linker to use Fortran libraries
Some C-Fortran interfaces must also agree on:
Arrays: indexing and order
File descriptors and stdio
File permissions
The word function has different meanings in C and Fortran. Depending on the situation, the choice is important:
In C, all subprograms are functions; however, some may return a null (void) value.
In Fortran, a function passes a return value, but a subroutine does not.
When a Fortran routine calls a C function:
If the called C function returns a value, call it from Fortran as a function.
If the called C function does not return a value, call it as a subroutine.
When a C function calls a Fortran subprogram:
If the called Fortran subprogram is a function, call it from C as a function that returns a compatible data type.
If the called Fortran subprogram is a subroutine, call it from C as a function that returns a value of int (compatible to Fortran INTEGER*4) or void. A value is returned if the Fortran subroutine uses alternate returns, in which case it is the value of the expression on the RETURN statement. If no expression appears on the RETURN statement, and alternate returns are declared on SUBROUTINE statement, a zero is returned.
The tables below summarize the data sizes and default alignments for FORTRAN 77 and Fortran 90 data types. In both tables, note the following:
C data types int, long int, and long are equivalent (4 bytes). In a 64-bit environment and compiling with -xarch=v9 or v9a, long and pointers are 8 bytes. This is referred to as "LP64".
REAL*16 and COMPLEX*32, (REAL(KIND=16) and COMPLEX(KIND=16)), are available only on SPARC platforms. In a 64-bit environment and compiling with -xarch=v9 or v9a, alignment is on 16-byte boundaries.
Alignments marked 4/8 for SPARC indicate that alignment is 8-bytes by default, but on 4-byte boundaries in COMMON blocks. The maximum alignment in COMMON is 4-bytes.
The elements and fields of arrays and structures must be compatible.
You cannot pass arrays, character strings, or structures by value.
You can pass arguments by value from f77 to C, but not from C to f77, since %VAL() is not allowed in a Fortran dummy argument list.
Table 11-1 shows the sizes and allowable alignments for FORTRAN 77 data types. It assumes no compilation options affecting alignment or promoting default data sizes are applied. (See also the FORTRAN 77 Language Reference Manual).
Table 11-1 Data Sizes and Alignments--(in Bytes) Pass by Reference (f77 and cc)
FORTRAN 77 Data Type |
C Data Type |
Size |
Default Alignment SPARC x86 |
|
---|---|---|---|---|
BYTE X CHARACTER X CHARACTER*n X |
char x unsigned char x unsigned char x[n] |
1 1 n |
1 1 1 |
1 1 1 |
COMPLEX X COMPLEX*8 X DOUBLE COMPLEX X COMPLEX*16 X COMPLEX*32 X |
struct {float r,i;} x; struct {float r,i;} x; struct {double dr,di;}x; struct {double dr,di;}x; struct {long double dr,di;} x; |
8 8 16 16 32 |
4 4 4/8 4/8 4/8/16 |
4 4 4 4 -- |
DOUBLE PRECISION X REAL X REAL*4 X REAL*8 X REAL*16 X |
double x float x float x double x long double x |
8 4 4 8 16 |
4/8 4 4 4/8 4/8/16 |
4 4 4 4 -- |
INTEGER X INTEGER*2 X INTEGER*4 X INTEGER*8 X |
int x short x int x long long int x |
4 2 4 8 |
4 2 4 4 |
4 2 4 4 |
LOGICAL X LOGICAL*1 X LOGICAL*2 X LOGICAL*4 X LOGICAL*8 X |
int x char x short x int x long long int x |
4 1 2 4 8 |
4 1 2 4 4 |
4 1 2 4 4 |
The following table similarly compares the Fortran 90 data types with C.
Table 11-2 Data Sizes and Alignment--(in Bytes) Pass by Reference (f90 and cc)
Fortran 90 Data Type |
C Data Type |
Size |
Alignment |
|
---|---|---|---|---|
CHARACTER x |
unsigned char x ; | 1 | 1 | |
CHARACTER (LEN=n) x |
unsigned char x[n] ; | n | 1 | |
COMPLEX x |
struct {float r,i;} x; | 8 | 4 | |
COMPLEX (KIND=4) x COMPLEX (KIND=8) x COMPLEX (KIND=16) x |
struct {float r,i;} x; struct {double dr,di;} x; struct {long double, dr,di;} x; |
8 16 32 |
4 4/8 4/8/16 |
|
DOUBLE COMPLEX x | struct {double dr, di;} x; | 16 | 4/8 | |
DOUBLE PRECISION x |
double x ; | 8 | 4 | |
REAL x |
float x ; | 4 | 4 | |
REAL (KIND=4) x REAL (KIND=8) x REAL (KIND=16) x |
float x ; double x ; long double x ; |
4 8 16 |
4 4/8 4/8/16 |
|
INTEGER x |
int x ; | 4 | 4 | |
INTEGER (KIND=1) x INTEGER (KIND=2) x INTEGER (KIND=4) x INTEGER (KIND=8) x |
signed char x ; short x ; int x ; long long int x; |
1 2 4 8 |
4 4 4 4 |
|
LOGICAL x |
int x ; | 4 | 4 | |
LOGICAL (KIND=1) x LOGICAL (KIND=2) x LOGICAL (KIND=4) x LOGICAL (KIND=8) x |
signed char x ; short x ; int x ; long long int x; |
1 2 4 8 |
4 4 4 4 |
C and Fortran take opposite perspectives on case sensitivity:
C is case sensitive--case matters.
Fortran ignores case.
The f77 and f90 default is to ignore case by converting subprogram names to lowercase. It converts all uppercase letters to lowercase letters, except within character-string constants.
There are two usual solutions to the uppercase/lowercase problem:
In the C subprogram, make the name of the C function all lowercase.
Compile the f77 program with the -U option, which tells f77 to preserve existing uppercase/lowercase distinctions on function/subprogram names.
Use one of these two solutions, but not both.
Most examples in this chapter use all lowercase letters for the name in the C function, and do not use the f77 -U compiler option. (f90 does not have an equivalent option.)
The Fortran compiler normally appends an underscore (_) to the names of subprograms appearing both at entry point definition and in calls. This convention differs from C procedures or external variables with the same user-assigned name. If the name has exactly 32 characters, the underscore is not appended. All Fortran library procedure names have double leading underscores to reduce clashes with user-assigned subroutine names.
There are three usual solutions to the underscore problem:
In the C function, change the name of the function by appending an underscore to that name.
Use the f77 C() pragma to tell the FORTRAN 77 compiler to omit those trailing underscores.
Use the f77 -ext_names option to make external names without underscores.
Use only one of these solutions.
The examples in this chapter could use the FORTRAN 77 C() compiler pragma to avoid underscores. The C() pragma directive takes the names of external functions as arguments. It specifies that these functions are written in the C language, so the Fortran compiler does not append an underscore as it ordinarily does with external names. The C()directive for a particular function must appear before the first reference to that function. It must also appear in each subprogram that contains such a reference. The conventional usage is:
EXTERNAL ABC, XYZ !$PRAGMA C( ABC, XYZ )
If you use this pragma, the C function does not need an underscore appended to the function name.
Fortran 90 does not have equivalent methods for avoiding underscores. Trailing underscores are required in the names of C routines called from Fortran 90 routines.
In general, Fortran routines pass arguments by reference. In a call, if you enclose an argument with the f77 and f90 nonstandard function %VAL(), the calling routine passes it by value.
In general, C passes arguments by value. If you precede an argument by the ampersand operator (&), C passes the argument by reference using a pointer. C always passes arrays and character strings by reference.
Except for arguments that are character strings, Fortran and C pass arguments in the same order. However, for every argument of character type, the Fortran routine passes an additional argument giving the length of the string. These are long int quantities in C, passed by value.
The order of arguments is:
Address for each argument (datum or function)
A long int for each character argument (the whole list of string lengths comes after the whole list of other arguments)
This Fortran code fragment: Is equivalent to this in C: CHARACTER*7 S INTEGER B(3) ... CALL SAM( S, B(2) ) char s[7]; long b[3]; ... sam_( s, &b[1], 7L ) ;
Array indexing and order differ between Fortran and C.
C arrays always start at zero, but by default Fortran arrays start at 1. There are two usual ways of approaching indexing.
You can use the Fortran default, as in the preceding example. Then the Fortran element B(2) is equivalent to the C element b[1].
You can specify that the Fortran array B starts at B(0) as follows:
INTEGER B(0:2)
This way, the Fortran element B(1) is equivalent to the C element b[1].
Fortran arrays are stored in column-major order: A(3,2)
A(1,1) A(2,1) A(3,1) A(1,2) A(2,2) A(3,2) A(1,3) A(2,3) A(3,3)
C arrays in row-major order: A[3][2]
A[0][0] A[0][1] A[0][2] A[1][0] A[1][1] A[1][2] A[2][0] A[2][1] A[2][2]
For one-dimensional arrays, this is no problem. For two-dimensional and higher arrays, be aware of how subscripts appear and are used in all references and declarations--some adjustments might be necessary.
For example, it may be confusing to do part of a matrix manipulation in C and the rest in Fortran. It might be preferable to pass an entire array to a routine in the other language and perform all the matrix manipulation in that routine to avoid doing part in C and part in Fortran.
Fortran I/O channels are in terms of unit numbers. The I/O system does not deal with unit numbers but with file descriptors. The Fortran runtime system translates from one to the other, so most Fortran programs do not have to recognize file descriptors.
Many C programs use a set of subroutines, called standard I/O (or stdio). Many functions of Fortran I/O use standard I/O, which in turn uses operating system I/O calls. Some of the characteristics of these I/O systems are listed in in the following table.
Table 11-3 Comparing I/O Between Fortran and C
Fortran Units |
Standard I/O File Pointers |
File Descriptors |
|
---|---|---|---|
Files Open |
Opened for reading and writing |
Opened for reading; or Opened for writing; or Opened for both; or Opened for appending; See OPEN(3S) |
Opened for reading; or Opened for writing; or Opened for both |
Attributes |
Formatted or unformatted |
Always unformatted, but can be read or written with format-interpreting routines |
Always unformatted |
Access |
Direct or sequential |
Direct access if the physical file representation is direct access, but can always be read sequentially |
Direct access if the physical file representation is direct access, but can always be read sequentially |
Structure |
Record |
Byte stream |
Byte stream |
Form |
Arbitrary nonnegative integers from 0-2147483647 |
Pointers to structures in the user's address space |
Integers from 0-1023 |
C programs typically open input files for reading and output files for writing or for reading and writing. A f77 program can OPEN a file READONLY or with READWRITE='READ' or 'WRITE' or 'READWRITE'. f90 supports the READWRITE specifier, but not READONLY.
Fortran tries to open a file with the maximum permissions possible, first for both reading and writing, then for each separately.
This event occurs transparently and is of concern only if you try to perform a READ, WRITE, or ENDFILE operation but you do not have permission. Magnetic tape operations are an exception to this general freedom, since you can have write permissions on a file, but not have a write ring on the tape.
To link the proper Fortran and C libraries, use the f77 or f90 command to invoke the linker.
demo% cc -c RetCmplxmain.c demo% f77 RetCmplx.f RetCmplxmain.o ¨ This command line does the linking. demo% a.out 4.0 4.5 8.0 9.0 demo%