[net.lang.f77] C calls FORTRAN subroutine

woods@hao.UUCP (Greg "Bucket" Woods) (10/13/84)

> In the C program, I have
> ----------
> #include <stdio.h>
> 
> main()
> {
> try_()
> }
> ----------
> 
> In the Fortran program, I have
> ----------
>       subroutine try
>       write (6,100)
> 100   format ("subprogram")
>       end
> ----------
> 

  This is a weird one. I know why it doesn't work, but knowing why isn't much
help. I put an "fflush(stdout)" call in the main program after the call to
"try", and then ran "adb" on this program, putting a breakpoint in "write".
The result of that shows that it is trying to write the string "subprogram"
on file descriptor 3. How about it, compiler wizards? What the '&"#%@*! is
going on?

--Greg
-- 
{ucbvax!hplabs | allegra!nbires | decvax!stcvax | harpo!seismo | ihnp4!stcvax}
       		        !hao!woods
   
     "...the bus came by, and I got on, that's when it all began..."

donn@utah-gr.UUCP (Donn Seeley) (10/13/84)

From the original article by Aldrin Leung:

	In the C program, I have
	----------
	#include <stdio.h>
	
	main()
	{
	try_()
	}
	----------
	
	In the Fortran program, I have
	----------
	      subroutine try
	      write (6,100)
	100   format ("subprogram")
	      end
	----------

When these routines are compiled, loaded together and run, they print
nothing.

The problem here is that f77's I/O system needs to be 'primed'.  The
standard f77 main() routine does this for you, but if you substitute
your own C main() routine then you have to do the 'priming' yourself.
There is an f77 I/O clean-up routine which you can call too (it's
not as important, though).  Without the 'priming', f77 I/O (at least
on pre-defined units) will have no effect.  A demonstration of the
the use of the priming and clean-up routines appears below.

Since f77 uses the C stdio library, you can mix C and f77 I/O by using
stdio in your C routines rather than straight Unix system calls.  Since
it may be difficult to predict which stdio file pointers are associated
with which f77 unit numbers, it's probably a good idea to stick with
'stdin', 'stdout' and 'stderr' when doing C I/O.

One other thing that is useful to have is a MAIN_() routine.  This is
normally created by f77 when it compiles the MAIN section of a program,
but if you replace the f77 main() with a C main(), it never gets
defined and f77 will complain about it if you use f77 to compile or
load your program.  (Yes, f77 will compile C files, one of its many
peculiar features.  Yes, this is useful because it means you can get
all of the f77 libraries without having to specify them explicitly, as
you would if you loaded your C and f77 objects 'by hand'.  Again, see
below for an example of this.)

Here's an example that demonstrates all of these features.  Put the
following code in a file 'c_main.c':

------------------------------------------------------------------------
# include	<stdio.h>

main( argc, argv, envp )
	int		argc;
	char		**argv;
	char		**envp;
{
	/*
	 * Process your arguments and environment here.
	 */

	/*
	 * Prime the f77 I/O routines, call MAIN_(), and clean up.
	 */
	f_init();
	MAIN_();
	f_exit();
	exit( 0 );
}

MAIN_()
{
	/*
	 * Call various f77 and C routines.
	 */
	c_routine();
	f77routine_();
}

c_routine()
{
	printf( "First some C I/O, then" );
}
------------------------------------------------------------------------

Put the following code in a file named 'f77_routines.f':

------------------------------------------------------------------------
	subroutine f77routine()

	print *, 'some f77 I/O.'

	return
	end
------------------------------------------------------------------------

Then compile the two files like this:

------------------------------------------------------------------------
% f77 c_main.c f77_routines.f -o cf
c_main.c:
f77_routines.f:
   f77routine:
%
------------------------------------------------------------------------

When you run the program, you get:

------------------------------------------------------------------------
% ./cf
First some C I/O, then  some f77 I/O.
%
------------------------------------------------------------------------

I hope this wasn't too complicated,

Donn Seeley    UCSD Chemistry Dept.       ucbvax!sdcsvax!sdchema!donn
32 52' 30"N 117 14' 25"W  (619) 452-4016  sdcsvax!sdchema!donn@nosc.ARPA

chris@umcp-cs.UUCP (Chris Torek) (10/13/84)

Doesn't the 4.2BSD f77 I/O library require a call to ``ioinit'' first?
-- 
(This mind accidently left blank.)

In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (10/16/84)

Exactly.  The Fortran I/O system requires initialization, and a C main
program will not do it by default.

leiby@masscomp.UUCP (10/22/84)

Regarding the fellow who calls a FORTRAN subroutine from his C
program and is then unable to do I/O from within the FORTRAN
subroutine:

The problem here is that the FORTRAN start-up code maps logical
unit numbers to Unix(tm) file descriptors in an implementation
dependent way.  Since the main program is in C, none of this
setup gets done.  Thus when the FORTRAN I/O library call is
executed, it can't find a valid logical unit number table,
and the output (if any) is trashed.  I'd be amazed if the fellow
gets any output at all.

A solution?  Unless you have the compiler code to look at, I'm
afraid it's like the old joke:

	Patient:  Dr., it hurts when I do this.
	Doctor:	  Well, don't do that!!!

		Mike Leibensperger
		{decvax,ihnp4,harpo,tektronix}!masscomp!leiby
-- 
Mike Leibensperger
{decvax,tektronix,harpo}!masscomp!leiby
Masscomp; One Technology Park; Westford MA 01886

joels@tektronix.UUCP (Joel Swank) (10/31/84)

> Regarding the fellow who calls a FORTRAN subroutine from his C
> program and is then unable to do I/O from within the FORTRAN
> subroutine:
> 
> The problem here is that the FORTRAN start-up code maps logical
> unit numbers to Unix(tm) file descriptors in an implementation
> dependent way.  Since the main program is in C, none of this
> setup gets done.  Thus when the FORTRAN I/O library call is
> executed, it can't find a valid logical unit number table,
> and the output (if any) is trashed.  I'd be amazed if the fellow
> gets any output at all.
> 
> A solution?  Unless you have the compiler code to look at, I'm
> afraid it's like the old joke:
> 
I had this problem under 4.2bsd and I found that output was going to
a file called fort.6. I circumvented the problem using a symbolic
link:
      ln -s /dev/tty fort.6

Just execute this command before running the program, and output will
go to the terminal.

Joel Swank
Software Center Tools Support
50-487
Tektronix
Beaverton OR 97077
(503) 627-4403