[comp.lang.fortran] Calling FORTRAN routines from C

dmocsny@minerva.che.uc.edu (Daniel Mocsny) (12/11/90)

In keeping with the holiday spirit of peace on earth and goodwill
toward language partisans, I have been toying with the possibility
of linking C and FORTRAN compiled objects together. To my surprise,
C and FORTRAN can coexist in harmony greater than their proponents
often do. However, all is not bliss.

Consider the following example. Suppose I have a library of compiled
objects originally written in FORTRAN, and I have no access to source
code. I wish to call some functions in this library from a C program,
and I want to use functions that calculate and return single precision
(float) values. To test this, I am using the following toy program:

/* file: main.c
 *
 * This is a C language main program which is supposed to call a 
 * function in a FORTRAN file test.f.
 */
#include <stdio.h>
float xsquar_( /* float x */ );
main() {
	float x, z;
	x = 5.0;
	z = xsquar_( &x );
	printf("The square of %g should be: %g\n", x, z );
}

Next, the FORTRAN file containing the XSQUAR function:

C file: test1.f
C
C This is a FORTRAN file containing a function I am trying to call from 
C a C program.
      REAL FUNCTION XSQUAR( X )
      REAL X
      XSQUAR = X * X
      WRITE(6,10) X, XSQUAR
10    FORMAT( "X: ",F10.3," XSQUAR: ",F10.3 )
      RETURN
      END

The underscore "_" character after xsquar in main.c is necessary on
several systems where I have tested this example, because the f77 
compiler appends an underscore to identifier names on these systems.

On a DEC MicroVAX II running Ultrix-32 v3.0, and on an HP machine
runnin HP-UX Release A.B3.10C, this example does what it it should,
i.e. (except that HP-UX doesn't need the underscore...sigh):

X:      5.000 XSQUAR:     25.000
The square of 5 should be: 25

However, under SunOS 4.0.3, I get the following:

X:      5.000 XSQUAR:     25.000
The square of 5 should be: 8.05306e+08

As nearly as I can tell, the Sun C compiler is having a little trouble
with the return value from xsquar_(). I have already tried the obvious
things: compiling with the -fsingle option (this doesn't help, because
it doesn't affect function return values); and trying all manner of casts
and declarations to double in main.c (maybe I haven't hit on the
right combinations, but I tried a few).

I did try the following, where I changed XSQUAR to a SUBROUTINE and
got the return value by passing a pointer to float from a file main2.c:

/* file: main2.c
 *
 * This is a C language main program which is supposed to call a 
 * subroutine in a FORTRAN file test2.f.
 */
#include <stdio.h>
void xsquar_( /* float x, float y */ );
main() {
	float x, y;
	x = 5.0;
	xsquar_( &x, &y );
	printf("The square of %g should be: %g\n", x, y );
}

The corresponding FORTRAN file is:

C file: test2.f
C
      SUBROUTINE XSQUAR( X, Y )
      REAL X, Y
      Y = X * X
      WRITE(6,10) X, Y
10    FORMAT( "X: ",F10.3," X squared: ",F10.3 )
      RETURN
      END

And the output is:

X:      5.000 X squared:     25.000
The square of 5 should be: 25

Here is the Makefile I used on the Sun, in case anybody wants to 
try this out:

# This is a Makefile to test calling a FORTRAN function from a
# C language main program.
FORTLIB=/home/f77/SC0.0/libF77.a
test: main.o test.o
	cc test.o main.o $(FORTLIB) -o test
test2: main2.o test2.o
	cc test2.o main2.o $(FORTLIB) -o test2

(The libF77.a FORTRAN library is in a non-standard location on the
machine I used. Change to the location on your machine. The WRITE
statement in test.f and test2.f will cause a link error unless
"ld" knows where to look for libF77.a. Since I used "cc" to generate
the "ld" command, and let "make" use its default rules on the
targets *.o, "ld" doesn't automatically find libF77.a.)

Does anybody have any suggestions about how to call FORTRAN functions
that return single-precision values from a C program under SunOS,
or is this an insurmountable problem? And does it occur under other
compiler combinations? Already this is looking uglier and less portable
than I would like.



--
Dan Mocsny				Snail:
Internet: dmocsny@minerva.che.uc.edu	Dept. of Chemical Engng. M.L. 171
	  dmocsny@uceng.uc.edu		University of Cincinnati
513/751-6824 (home) 513/556-2007 (lab)	Cincinnati, Ohio 45221-0171

3003jalp@ucsbuxa.ucsb.edu (Applied Magnetics) (12/13/90)

In article <6928@uceng.UC.EDU> dmocsny@minerva.che.uc.edu (Daniel Mocsny) writes:

> [problems recovering a Fortran function value from a C program.]

That's a new one.  My own C-Fortran chimeras always give me trouble
with the following:
  -I/O.  The C and Fortran I/O subsystems may interfere.  Do all I/O
   in the same language or else...
  -Common blocks.  There may be no way to get at a common block from C.
The documentation is not always complete or clear in these two areas.
"Ordinary" function and subroutine calls usually work.  Needless to
say, all this is system-dependent.  I guess I can add function calls to
my watch list.

In the case at hand, subroutine calls seem to work.  You can always
write a Fortran subroutine through which you will call the Fortran
function from C.

--Pierre Asselin, R&D, Applied Magnetics Corp.  I speak for me.