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.