# Part 4, Mixing ANSI-C with Fortran 77 or Fortran 90

## "Portability or Transportability?"

### Presented at the IFIP WG 2.5 International Workshop on "Current Directions in Numerical Software and High Performance Computing", 19 - 20 October 1995, Kyoto, Japan.

Bo Einarsson
National Supercomputer Centre
Linköping University
S-581 83 LINKÖPING
SWEDEN

CONTENTS

## 1. INTRODUCTION.

In this paper I discuss mixing some very simple procedures written in ANSI-C with procedures written in Fortran 77 but using either a Fortran 77 or a Fortran 90 compiler.

The tests have been done on Silicon Graphics (IRIX 4.0.1 and 5.3), DEC MIPS ULTRIX, DEC Alpha (Digital UNIX), and Sun OS 4.1.3.

The supercomputers Cray Y-MP (UNICOS 8.0.3.1), MasPar, and Parsytec are also discussed.

The results are rather conflicting, some combinations are permitted on some systems but not on others. Unfortunately, not all three compilers have been available for me on all the tested systems.

## 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
```
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 <stdio.h>
#include <math.h>

/*     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 some extra 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 C case on Silicon Graphics (IRIX 4.0.1)
```% cc -c c2sam.c
% f77 -c sam.f
% cc -o all c2sam.o sam.o -lF77
% all
6 648 Bo G E
```
On Silicon Graphics with IRIX 5.3 this also worked, but the output was appended with some rubbish! I have not yet found the reason for this irregularity. Also with the GNU compiler, gcc version 2.6.3, exactly the same happened.

Compilation and linking in the C case on Sun OS 4.1.3, using the GNU compiler, gcc version 2.3.3, and Fortran 77:

```% gcc -c c2sam.c
% f77 -c sam.f
% gcc -o all c2sam.o sam.o -lF77 -lm
% all
6 648 Bo G E
```
or with Fortran 90:
```% gcc -c c2sam.c
% f90 -c sam.f
% gcc -o all c2sam.o sam.o /usr/local/lib/f90/libf90.a
% all
6 648 Bo G E
```
With Fortran as the linker, the result was "Undefined: __main" for both Fortran 77 and Fortran 90 combined with the gcc compiler.

On Sun the compilation failed with the default C compiler (not ANSI-C).

On DEC MIPS ULTRIX no specification of extra libraries were required in most cases. I used all eight combinations of f77, f90, cc and gcc (version 2.5.8). With Fortran 77 or Fortran 90 and the GNU compiler the Fortran linking failed "Undefined: __main". Using the Fortran 90 compiler and linking with any C linker required explicit mentioning of the Fortran 90 library

```	cc  sam.o c2sam.o /usr/local/NAGWare_f90/lib/libf90.a
gcc sam.o c2sam.o /usr/local/NAGWare_f90/lib/libf90.a
```

On DEC Alpha (Digital UNIX) I used f90 and cc. It worked without extra libraries with C as the linking language, but failed with Fortran 90 ("c2sam.o: main: " multiply defined and "MAIN__" unresolved).

## 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 <stdio.h>
#include <math.h>

/*      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 -lI77 -lisam
% allac
99
```
The above works with both IRIX 4.0.1 and IRIX 5.3. When using IRIX 5.3 and gcc, both the Fortran and the gcc linking worked fine.

On the Sun OS 4.1.3 the standard method worked with f77 and with gcc the libraries "-lF77 -lm" were required, while with the default cc only "-lF77" was required.

Switching to Fortran 90 there were still no problems if Fortran was the linking language, but linking with cc required explicit mentioning of "/usr/local/lib/f90/f90lib.a" and linking with gcc in addition required the "-lm" switch.

On DEC MIPS ULTRIX no specification of extra libraries were required when Fortran was used as the linker. I used all eight combinations of f77, f90, cc and gcc (version 2.5.8). Using the Fortran 77 compiler and linking with any C linker required an impressive command

```% cc  mlp3.o mlp4.o -lfor -lutil -li -lots -lUfor
% gcc mlp3.o mlp4.o -lfor -lutil -li -lots -lUfor
```
Using the Fortran 90 compiler and linking with any C linker required explicit mentioning of the Fortran 90 library
```% cc  mlp3.o mlp4.o /usr/local/NAGWare_f90/lib/libf90.a
% gcc mlp3.o mlp4.o /usr/local/NAGWare_f90/lib/libf90.a
```
On DEC Alpha (Digital UNIX) I used f90 and cc. It worked with Fortran 90 without any explicit libraries, but failed with C as the linking language (unresolved "main"), when I used the following command:
```% cc -o all mlp3.o mlp4.o -lfor -lutil -lots
```

## 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 <stdio.h>
#include <math.h>

/*      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 on all the tested systems.
```% f77 -o all mlp1.o mlp2.o
% all
786 3.200000

% cc -o allc mlp1.o mlp2.o
% allc
786 3.200000
```
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
331 -rwxr-xr-x   1 boein      169464 Aug 17 13:50 all*
81 -rwxr-xr-x   1 boein       40988 Aug 17 13:51 allc*
%
```
The above works with both IRIX 4.0.1 and IRIX 5.3. When using IRIX 5.3 and gcc, the Fortran linker complained about unresolved "__main", but the gcc linking worked fine.

On the Sun OS 4.1.3 the standard method worked both with f77 and f90 and the default cc.

Compiling with the GNU compiler gcc, the f77 or f90 linking did not work, resulting in an error message "Undefined symbol __main". Linking with gcc worked fine.

On DEC MIPS ULTRIX I used all eight combinations of f77, f90, cc and gcc (version 2.5.8). Everything worked with the exception of using a Fortran linker with a procedure compiled with the GNU C compiler. In these cases "Undefined: __main" was obtained.

On DEC Alpha (Digital UNIX) I used f90 and cc. It worked fine with C as the linking language, but failed with Fortran 90, complaining about multiply defined "main" and unresolved "MAIN__".

## 5. SUMMARY

In the table below I use the following symbols
```	*	Worked without any explicit libraries
+	Worked with explicit libraries
-	Failed
E	Compilation error
```
For each operating system, the first symbol refers to Fortran as the linker, the second to C as the linker. For blank cases I do not have a compiler of the required kind.

ExampleLanguages DEC SGI Sun
(section) UnixUltrix 4.0.15.3 4.1.3
2f77cc   ***+*+EE
f77gcc   -*  -+-+
f90cc -**+    EE
f90gcc   -+    -+
3f77cc   *+*+*+*+
f77gcc   *+  *+*+
f90cc *-*+    *+
f90gcc   *+    *+
4f77cc   ********
f77gcc   -*  -*-*
f90cc -***    **
f90gcc   -*    -*

## 6. SUPERCOMPUTERS

The supercomputers Cray Y-MP (UNICOS 8.0.3.1), MasPar, and Parsytec have a somewhat different attitude towards mixed language programming. It is not possible to use portable code in the same way as on conventional UNIX computers.

### CRAY

Cray has chosen a nice way to implement interlanguage communication. As described in chapter 11 "Interlanguage Communication" of the "Cray Standard C Reference Manual SR-2074 4.0", Cray permits calling Fortran from C as well as C from Fortran. In order to make this possible a new header and several utilities are introduced into C. In order to access blank COMMON from C, they suggest writing a simple Fortran function to return an address.

With the Cray method, at least one of the program units to be mixed has to be changed. The implementation is thus of "transportability" and not of "portability".

The Cray chapter 11 contains several examples and additional references to other relevant Cray documents.

### MASPAR

The main programming language of MasPar is MPL (DECmpp Programming Language or MasPar Programming Language). In short, MPL is C with Fortran 90 arrays. The command is "mpl". It is possible for Fortran front end programs to call an MPL subroutine. The Fortran dialect is MPF, which is Fortran 77 with Fortran 90 arrays. The command is "mpfortran". The command for C is "mpl_cc".

I have tried mixed language programming on MasPar MP-1 without any success so far. The linker did not find the routines.

Reference: Parallel Processing: A Self-Study Introduction, A First Course in Programming the DECmpp/Sx, Ron Pickering and Jeremy Cook, para//ab, Department of Informatics, University of Bergen, N-5020 BERGEN, Norway. Available as the file "DECmpp_study_guide.ps.Z" from "ftp.ii.uib.no" in the directory "/pub/tech_reports".

### PARSYTEC

We have a Parsytec GC/PowerPlus-128. It is a distributed memory computer based on the Motorola PowerPC 601. Its 128 processors deliver a theoretical peak performance of 10 Gflops.

I have tried mixed language programming on Parsytec without any success so far. The linker did not find the routines. The manuals I have checked do not mention mixed language programming or interlanguage communication.

### FUJITSU

The following paragraph on mixing Fortran and C on Fujitsu supercomputers was written by a company representative.

It is possible to mix procedures written in FORTRAN 77, 90, classical C, and standard C and there are no particular constraints in this area.

## 7. 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 used to be available, but now ANSI C dominates. It is only on the Sun OS 4.1.3 where I have the old version of C, but luckily I also have the new one available as the GNU C, gcc. 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

```% cat tpk.c
#include <stdio.h>
#include <math.h>

/*      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);
}
}
```
As an ANSI-C program it becomes
```% cat tpk-ansi.c
#include <stdio.h>
#include <math.h>

/*      Function declared */
double fun(double t);
/*      Program in C */

main()
{      /* No changes */
}
/*      Function defined */
double fun(double t)
{
return t*t;
}
```
In this paper I have mainly discussed ANSI-C. It is only on the Sun I have the conventional C. Some of the examples are from old manuals for the Silicon Graphics, using IRIX System V Release 3.3.1. Some revision has been done because of compiler development.

## 8. COMMENTS

The used Fortran 90 compiler has been the NAGWare f90 Compiler (Unix), except on the Cray and the DEC Unix, where the compiler from the hardware manufacturer has been used.

At the presentation Eric Grosse made two suggestions, which I will look into:

1. It ought to be able to remove the failures (indicated by - in the summary) through explicitly mentioning a certain library. This should remove the problem with the main routine!
2. It is probable that the problem in the first example (section 2) with some rubbish being appended to the output from IRIX 5.3 can be removed by properly including the trailing terminator already in the Fortran version, as the last character.

Another question was about mixed language programming on PC:s. This was not covered in the talk. Some references are those by Microsoft and NAG in the bibliography.

For references please see my bibliograhy on mixed language programming.

My own papers on mixed language programming are listed here.

Last modified: 3 April 1996
boein@nsc.liu.se