In this example, the command line is read to find out how large to
make the arrays. This could be done also by calling a Fortran
routine to pre-read the data file to determine the array size instead.
arrays are dynamically allocated by C and then are
passed off to
a F77 routine. Wherever these arrays are used they must be passed
via the routine argument list along with the array size.
C main function
This C main function reads the command line arguments and
allocates memory according to the value given at the command line
then passes it off to the Fortran subroutine.
main.c:
#include <stdio.h> #include <stdlib.h> #ifdef _CRAY # include <fortran.h> # define f77sub F77SUB #else # if !defined(_AIX) && !defined(__hpux) # define f77sub f77sub_ # endif # define _fcd char * # define _cptofcd(a,b) (a) # define _fcdlen(a) strlen(a) #endif void f77sub(int *nlen, int *iarray, double *array); void usage(char *PN, long DF) { (void) printf( "\n" "%s - an advance example of C & Fortran intermixing.\n" " Use C for command line processing and memory allocation,\n" " Use Fortran for numerical processing and access to the\n" " vast assortment of numerical libraries.\n" "\n" "usage: %s [-h] [-x #]\n" " -h prints this usage info\n" " -x # Use # as the array size (default = %d)\n" "\n", PN, PN, DF); return; } /* C naturally allows command line processing ... so make use of it*/ int main(int argc, char *argv[]) { int defsize = 10; int size = defsize; char *ProgName = *argv++; char *ptr; int *iarray; double *array; /* expect '-x' option to set array sizes */ while (*argv) { ptr = *argv; if (*ptr == '-') { /* got some option */ switch(*(++ptr)) { case 'h': usage(ProgName, defsize); return 1; break; case 'x': size = (int) atol(*(++argv)); break; } } argv++; } /* allocate space */ (void) fprintf(stderr,"Setting array size = %ld\n", size); if ((iarray = (int *) malloc(((size_t) size)*sizeof(int))) == (int *) NULL) { (void) fprintf(stderr,"Failed to allocate space for IARRAY\n"); return 2; } if ((array = (double *) malloc(((size_t) size)*sizeof(double))) == (double *) NULL) { (void) fprintf(stderr,"Failed to allocate space for ARRAY\n"); return 3; } /* call the Fortran subroutine with these arrays */ f77sub(&size, iarray, array); return 0; }
subf77.F:
#ifdef F77PROGRAM program f77sub implicit double precision (a-h,o-z), integer (i-n) parameter (ilen = 100) #else subroutine f77sub(ilen, iarray, array) implicit double precision (a-h,o-z), integer (i-n) #endif dimension iarray(ilen), array(ilen) c c example F77 routine to demonstrate advance C & F77 intermixing. c The arrays were dynamically allocated using C's malloc. c Many F77 compilers support some sort of ALLOC() call, but none c are standard F77, whereas it is standard to C. c However, care must be exercised when calling F77 from C since c F77 is case-insensitive and C isn't. See the templates for further c info. c c by R.K.Owen,PhD 01/12/97 c parameter (ZERO = 0.0d0) c c fill arrays do 100 i=1,ilen iarray(i) = i array(i) = ZERO 100 continue c c iarray = sums of integers do 110 i=1,ilen-1 iarray(i+1) = iarray(i+1) + iarray(i) 110 continue c c array = log10 of iarray do 120 i=1,ilen array(i) = LOG10(DFLOAT(iarray(i))) 120 continue c c if more than 6 elements print out 1st & last 3 if (ilen .le. 6) then write(6,1000) (i, iarray(i), array(i), i=1,ilen) else write(6,1000) (i, iarray(i), array(i), i=1,3) write(6,'(1x,". . .")') write(6,1000) (i, iarray(i), array(i), i=ilen-2,ilen) endif return 1000 format (1x,i5, i10, f16.6) end
% a.out -h a.out - an advance example of C & Fortran intermixing. Use C for command line processing and memory allocation, Use Fortran for numerical processing and access to the vast assortment of numerical libraries. usage: a.out [-h] [-x #] -h prints this usage info -x # Use # as the array size (default = 10) % a.out -x 20000 Setting array size = 20000 1 1 0.000000 2 3 0.477121 3 6 0.778151 . . . 19998 199970001 8.300965 19999 199990000 8.301008 20000 200010000 8.301052 % a.out Setting array size = 10 1 1 0.000000 2 3 0.477121 3 6 0.778151 . . . 8 36 1.556303 9 45 1.653213 10 55 1.740363