(Dr.R.K.) Fortran & C - Allocating Memory

Go to Top Go to Bottom blank blank Go up one level R.K.'s Home Page Keyword Index Site Map Help Linux

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)
      end

Output 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

Brought to you by: R.K. Owen,Ph.D.
This page is http://rkowen.owentrek.com/howto/FandC/FandC.mem.html