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