home *** CD-ROM | disk | FTP | other *** search
- Xref: sparky comp.lang.c:20066 comp.lang.fortran:5123
- Newsgroups: comp.lang.c,comp.lang.fortran
- Path: sparky!uunet!usc!sol.ctr.columbia.edu!phoenix!bobp
- From: bobp@msi.com (Bob Pitha)
- Subject: Re: calling a Fortran subroutine from a C program
- Followup-To: comp.lang.c,comp.lang.fortran
- References: <1jmqdaINN11g@mudhoney.mathcs.emory.edu>
- Sender: nobody@ctr.columbia.edu
- Organization: Molecular Simulations, Inc.
- Date: Fri, 22 Jan 1993 13:07:43 GMT
- X-Newsreader: TIN [version 1.1 PL8]
- Message-ID: <1993Jan22.130743.27130@sol.ctr.columbia.edu>
- X-Posted-From: phoenix.msi.com
- NNTP-Posting-Host: sol.ctr.columbia.edu
- Lines: 114
-
- Scott White (swhite@mathcs.emory.edu) wrote:
- : Can someone please tell me how to call a Fortran subroutine from a C program?
- : The environment is sun4, OS 4.1.2.
-
- Sure, this isn't really that hard as long as you keep a few basic issues in
- mind:
-
- 1) Function names: Fortran is a case-insensitive language, so typically
- Fortran compilers convert names to entirely upper- or lower-case. The
- sun compiler does lowercase; it also appends an underscore to the end
- of the function name. Thus, a Fortran subroutine named MyFortranSub
- would be exported to the linker as myfortransub_. There is an option
- for the compiler to preserve case, I think it's -U, but I'll assume
- you're not using it.
-
- 2) Arguments: Fortran always expects pointers in its argument list. So
- always pass an address from C.
-
- 3) Arrays: There are a couple of insidious issues with arrays: first,
- remember that C arrays start from 0, and Fortran from 1. So if you
- assign a value in C to element [3], you should access it in the Fortran
- subroutine as element (4). Alternately, declare your arrays in Fortran
- to explicitly start from 0. I don't like to do that, but you can inf
- you want.
- Multi-dimensional arrays can be a headache, too, because it's easy to
- get the order of the subscripts mixed up. C arrays are stored such that
- the second subscript varies faster than the first: x[2][2] is stored in
- memory in the following order: x[0][0]; x[0][1]; x[1][0]; x[1][1]. It's
- exactly the opposite in Fortran; the array x (2,2) is stored as: x(1,1);
- x(2,1); x(1,2); x(2,2). So remember to reverse the order of your
- subscripts when accessing multidimenstional arrays.
-
- 4) Character arrays: For each character array in the argument list, there
- should be a long int at the end of the argument list specifying the
- *declared* length of the array - that is, how much space is allocated
- for it. Since Fortran blank-fills character arrays, this number will
- specify how many places to fill. If you have more than one character
- array in the argument list, the length arguments should be in the same
- order as the character arguments.
-
- So now, here's a mocked-up example of how to do this. I'll try to keep
- it short but still touch on each concept to some extent:
-
- (in C):
-
- int int_arg;
- int int_array [3];
- int int_matrix [4][3];
- float float_arg;
- char string [12];
-
- strcpy (string, "test");
- int_array [1] = 37;
- int_matrix [2][1] = 54;
- myfortransub_ (&int_arg, &float_arg, int_array, int_matrix, string,
- (long) strlen (string));
-
-
- (and now the Fortran part)
-
- subroutine MyFortranSub (int_arg, float_arg, int_array,
- + int_matrix, string)
- integer int_arg
- real float_arg
- integer int_array (3)
- integer int_matrix (3, 4)
- character*(*) string
-
- int_array (2) should be 37
- int_matrix (2, 3) should be 54
- string should be "test"
-
- : Also, the called Fortran routine takes variables which are arrays as
- : parameters. And, I looked and saw that the subscripts start at 1, whereas in
- : C they start at zero. That's no problem is it (an address is an address):
-
- No, it's no problem, assuming you remember it everywhere. It only makes
- it a bit easier to make one of those annoying off-by-one subscript errors!
-
- : /* .c file */
- : int num[100];
- : double zeta[100];
-
- : foo(num, zeta);
-
-
- : /* .f file */
- : subroutine foo(number, gamma)
- : integer*4 number(100)
- : real*8 gamma(100)
-
- : /* program proceeds to manipulate values in the arrays, with subscripts
- : 1 through 100, not 0 through 99 */
-
- As said above, in your C file you should call foo_, not foo.
-
- : Finally, if the Fortran subroutine changes the values in gamma, the changes
- : show up when we return to the C program, right?
-
- Absolutely. In both the C function and the Fortran subroutine, gamma
- refers to the same 400 bytes of memory.
-
- There's a section in the Sun FORTRAN User's Guide that talks about
- C/Fortran interfaces. If you have the manual, it's worth reading. There
- are a lot of little picky issues I didn't touch on - and probably won't
- come up if you're doing something as simple as the foo function you use
- as an example.
-
- Good luck!
-
- -----------------------------------------------------------------------
- Bob Pitha Molecular Simulations Inc.
- bobp@msi.com 16 New England Executive Park
- (617) 229-9800 x242 Burlington, MA 01803-5297
-