Fortran & C - Allocating Memory |
Introduction
Fortran77 doesn't directly support dynamic memory allocation. However, many F77 compilers support some sort of ALLOC() call, but none are standard F77, whereas this type of operation is standard to C. Neither does F77 have a standard facility for reading the command line for options and arguments. This is standard to C also. (POSIX 1003 does provide some routines to Fortran for doing this, but it's probably more portable to use C instead.)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; }Fortran ``Program''
This Fortran subroutine may have been a ``program'' that declared the arrays in either common blocks or in the main program to some predefined size. Now it has been converted to a subroutine with the arrays passed to it.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) endOutput Results
% 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
Last Modified:
Brought to you by: R.K. Owen,Ph.D.
This page is http://owen.sj.ca.us/rkowen/howto/FandC/FandC.mem.html