Page 1 of 6 MIXED LANGUAGE PROGRAMMING Part 3, C and FORTRAN Draft 1991-05-08 Bo Einarsson NSC 1. ANSI-C AND CONVENTIONAL C. There are two main variants of C, the conventional one based on the book from 1978 by Brian Kernighan and Dennis Ritchie: The C Programming Language", and the in 1989 adopted standard, ANSI-C. On most computers, only the conventional C is available. At the moment I have ANSI-C on one VAX VMS, two Silicon Graphics and one Cray. On the Sun OS and on the Hewlett Packard HP-UX I only have access to the conventional C, although ANSI-C is forthcoming. The big difference is a new syntax for declaring and defining functions. The old was like Fortran in that nothing was checked, while the new is like Algol in that a lot is checked. To use ANSI-C thus increases the safety. Another change is the introduction of single precision. In conventional C all computations were performed in double precision on ordinary computers (but in single precision on the Cray). In addition records and unions, who have existed in many C-implementations, have been added to the standard, and finally the arithmetic properties have been clarified. You should note the backward compatibility in that the old way of declaring functions has been kept as a permitted alternative. Because of the increased safety I strongly urge you to adapt to the new form. A simple program in the old variant of C looks like #include #include /* Function */ double fun(t) double t; { return t*t; } /* Program in C */ main() { int i; double t; double y; double a[11]; for ( i = 0; i <= 10; i++ ) { t = i; y = fun(t); printf(" %lf \n",y); } } Page 2 As an ANSI-C program it becomes #include #include /* Function declared */ double fun(double t); /* Program in C */ main() { /* No changes */ } /* Function defined */ double fun(double t) { return t*t; } All examples below have been run on the Silicon Graphics, using IRIX System V Release 3.3.1. 2. USE OF A SUBROUTINE AND A FUNCTION WRITTEN IN FORTRAN FROM A PROGRAM WRITTEN IN C. We will here describe a case were first a program written in Fortran and then a routine written in C will call both a subroutine and a function written in Fortran. Both the main program and the subroutine calls the function. The main program in Fortran is in the file "f2sam.f" and is conventional. The subroutine and the function are in the file "sam.f". Running in Fortran is quite normal. % cat f2sam.f program f2sam external f integer f character*7 s integer b(3) call sam(f, b(2), s) write(6,10) b(2), f(real(b(2))), s 10 format(i5,i5,10x,a7) stop end % cat sam.f subroutine sam(f, b, s) external f character*7 s integer b, f x = 1.3 s = 'Bo G E ' b = f(x) end integer function f(x) f=3*x**3 return end Page 3 The corresponding routine in C is in the file "c2sam.c" and has the following peculiarities: 1) The indices in C have to be decreased with 1. 2) Both the subroutine "sam" and the function "f" have to be given an "underlining" at every occurrence in the C-routine, even inside the call of the Fortran-routine. 3) Since Fortran transfers parameters by reference, pointers have to be used in C. 4) As follows from the listing I had a problem with the call of the function inside the print-statement. I solved this in the ugly way by introducing the auxiliary variable x. % cat c2sam.c #include #include /* C Call to SAM in Fortran */ int f_(float); main() { char s[7]; int b[3]; float x; sam_(f_, &b[1], s, 7); x = b[1]; printf(" %d %d %s\n", b[1], f_(&x), s); } Compilation is done separately for the two languages, the switch -c interrupts the process after the assembly. Linking is normal if the main program is in Fortran, if it is in C a lot of libraries have to be mentioned explicitly. Compilation and linking in the Fortran case % f77 -c f2sam.f % f77 -c sam.f % f77 -o all f2sam.o sam.o % all 6 648 Bo G E Compilation and linking in the mixed case % cc -c c2sam.c % f77 -c sam.f % cc -o all c2sam.o sam.o -lF77 -lU77 -lI77 -lisam -lm % all 6 648 Bo G E Page 4 3. USE OF A MATRIX FROM FORTRAN AND C. We will here describe a case where a matrix element is assigned a value in a C-routine and is used in the calling Fortran-program. The main program in Fortran is in the file "mlp3.f" and is completely conventional. % cat mlp3.f integer a(2,3) call p(a,1,3) write (6,10) a(1,3) 10 format (1x,I9) stop end We perform the assignment in the C-routine p in the file "mlp4.c". This routine has the following peculiarities: 1) The indices in C and Fortran have to be reversed. 2) The indices in C have to be decreased with 1. 3) Since Fortran transfers parameters by reference, pointers have to be used in C. 4) The subroutine "p" has to be given an "underlining". % cat mlp4.c #include #include /* Array Handling */ void p_(a,i,j) int *i, *j, a[3][2]; { a[*j-1][*i-1] = 99; } Compilation is done separately for the two languages, the switch -c interrupts the process after the assembly. % cc -c mlp4.c % f77 -c mlp3.f Linking is normal if the most important program is in Fortran, if it is in C a lot of libraries have to be mentioned explicitly. Note that the choice of "most important" may be quite arbitrary. % f77 -o alla mlp3.o mlp4.o % alla 99 % cc -o allac mlp3.o mlp4.o -lF77 -lU77 -lI77 -lisam -lm % allac 99 Page 5 4. USE OF A COMMON BLOCK FROM FORTRAN IN A C-PROGRAM. We will here describe a case where two variables have been assigned values in a COMMON block with the name "namn", and these values are to be used in a C-program. We put the COMMON block into the subroutine "sam" in the file "mlp2.f". It is completely conventional. % cat mlp2.f subroutine sam() common /namn/ i, r i = 786 r = 3.2 return end The main program in C is in the file "mlp1.c" and has the following peculiarities: 1) The COMMON block is declared as a structure with the occurring variables defined in the ordinary C-style. The name "namn" of the COMMON block is given an "underlining". 2) The subroutine "sam" with the COMMON block is called, with an "underlining". 3) When the C-program requires the values of the COMMON block, the variables are qualified with the name of the block. % cat mlp1.c #include #include /* Accessing Common Blocks of Data */ struct S {int i; float r;} namn_; main() { sam_(); printf(" %d %f\n",namn_.i,namn_.r); } Compilation is done separately for the two languages, the switch -c interrupts the process after the assembly. % cc -c mlp1.c % f77 -c mlp2.f Linking is normal if the most important program is in Fortran, if it is in C a lot of libraries have to be mentioned explicitly. Note that the choice of "most important" may be quite arbitrary. % f77 -o all mlp1.o mlp2.o % all 786 3.200000 % cc -o allc mlp1.o mlp2.o -lF77 -lU77 -lI77 -lisam -lm % allc 786 3.200000 Page 6 Note that on the Silicon Graphics the Fortran system produces a much longer (in this case a factor 4) executable program than the C system. % lls 286 -rwxr-xr-x 1 boein 146392 Jan 10 12:56 all* 70 -rwxr-xr-x 1 boein 35772 Jan 10 12:58 allc* 1 -rw-r--r-- 1 boein 187 Jan 10 12:50 mlp1.c 2 -rw-r--r-- 1 boein 884 Jan 10 12:55 mlp1.o 1 -rw-r--r-- 1 boein 99 Jan 10 12:26 mlp2.f 2 -rw-r--r-- 1 boein 556 Jan 10 12:55 mlp2.o