These demo codes use the Cray C predefined macro _CRAY to conditionally compile any Cray dependent parts, _AIX for any IBM xlc dependent parts, and __hpux for HP machines. Most everything else are satisfied by the defaults.
Note that for the Cray that the C parts need to convert Fortran character strings to C char pointers. On workstations this is usually no problem. In addition, since Fortran is case insensitive Cray Fortran defaults subroutine names to UPPERCASE. Workstations default to lowercase with an underscore (_) usually appended to the name.
| Fortran | C | size(bits) |
|---|---|---|
INTEGER | int | 46/64 |
| cft77 -i64 | cc -nofastmd | |
INTEGER | long | 64 |
REAL | double or float | 64 |
DOUBLE PRECISION | long double | 128 |
COMPLEX | float complex or double complex | 128 |
SUBROUTINE SUBR( ) | void SUBR( ) | |
FUNCTION FN( ) | double FN( ) | |
COMMON /CB/data(10) | struct common { double data[10]; } CB; |
The demo codes use the IBM C predefined macro _AIX to conditionally compile any IBM dependent parts.
In addition, since Fortran is case insensitive IBM Fortran defaults subroutine names to lowercase and does not append or prepend an underscore (_) to the name.
| Fortran | C | size(bits) |
|---|---|---|
INTEGER*1 | signed char | 8 |
INTEGER*2 | short | 16 |
INTEGER | int | 32 |
REAL | float | 32 |
DOUBLE PRECISION | double | 64 |
COMPLEX | 2 float struct | 64 |
DOUBLE COMPLEX | 2 double struct | 128 |
SUBROUTINE SUBR( ) | void subr( ) | |
FUNCTION FN( ) | float fn( ) | |
COMMON /CB/data(10) | ? |
PROGRAM F2C
C
CHARACTER*32 NAME
INTEGER AGE
REAL TEMP
C
NAME = "Knut"
C add null character at end for portable & safe handling by C
NAME(LEN(NAME):LEN(NAME)) = CHAR(0)
C note that LEN(NAME) = 32 in this case
AGE = 4
TEMP = 98.6
CALL NAMEAGE(NAME, AGE, TEMP)
END
#include <string.h>
#ifdef _CRAY
# include <fortran.h>
# define nameage NAMEAGE
#else
# if !defined(_AIX) && !defined(__hpux)
# define nameage nameage_
# endif
# define _fcd char *
# define _fcdtocp(a) (a)
# define _fcdlen(a) strlen(a)
#endif
void nameage(_fcd name, int *age, float *temp) {
char *cp;
size_t len;
cp = _fcdtocp(name); /* convert to C char* */
len = _fcdlen(name);
/* strip trailing blanks */
while (cp[len-1] == ' ' || cp[len-1] == '\0') --len;
printf("Hello %.*s, who is %d years old, "
"has a temperature of %4.1f\n", len, cp, *age, *temp);
}
cc -c f2cfn.c
cf77 f2c.f f2cfn.o
xlc -c f2cfn.c
xlf f2c.f f2cfn.o
gcc -c f2cfn.c
f77 f2c.f f2cfn.o
gcc -c f2cfn.c
f77 f2c.f f2cfn.o
gcc -c f2cfn.c
f77 f2c.f f2cfn.o
gcc -c f2cfn.c
g77 f2c.f f2cfn.o
Hello Knut, who is 4 years old, has a temperature of 98.6
#include <string.h>
#ifdef _CRAY
# include <fortran.h>
# define nameage NAMEAGE
#else
# if !defined(_AIX) && !defined(__hpux)
# define nameage nameage_
# endif
# define _fcd char *
# define _cptofcd(a,b) (a)
# define _fcdlen(a) strlen(a)
#endif
void nameage(_fcd name, int *nlen, int *age, float *temp);
int main() {
char *name = "Knut";
_fcd fp;
int nlen,age = 4;
float temp = 98.6;
nlen = strlen(name);
fp = _cptofcd(name, nlen); /* convert to Fortran string */
nameage(fp, &nlen, &age, &temp);
return 0;
}
SUBROUTINE NAMEAGE(NAME, NLEN, AGE, TEMP)
CHARACTER*(*) NAME
INTEGER NLEN,AGE
REAL TEMP
C
WRITE(6,1000) NAME(1:NLEN),AGE,TEMP
1000 FORMAT(1X,'Hello ',A,', who is ',I2,
. ' years old, has a temperature of ', f4.1)
RETURN
END
-V or -v
option (or whatever) to get a verbose execution listing to show what
arguments are being passed to each compilation stage.
cf77 -c c2ffn.f
cc -c c2f.c
cf77 c2f.o c2ffn.o
xlf -c c2ffn.f
cc c2f.c c2ffn.o -lxlf90 -lxlf -lm
f77 -c c2ffn.f
gcc c2f.c c2ffn.o -lF77 -lm -lU77 -lI77 -lisam -lmpc -lc
f77 -c c2ffn.f
gcc c2f.c c2ffn.o -L/usr/lang/SC0.0 -lF77 -lm -lc
f77 -c c2ffn.f
gcc c2f.c c2ffn.o -lcl -lisamstub -lc
g77 -c c2ffn.f
gcc -c c2f.c
g77 c2f.o c2ffn.o
Hello Knut, who is 4 years old, has a temperature of 98.6