#include #include /* This example demonstrates how a C program can call FORTRAN subroutines and functions, and pass information back and forth. */ #define ARRSIZE 3 /* array size */ /* Here we are declaring the names of the routines we'll be calling. Note that the routines FOR1_, FOR2_, FOR3_ and FOR4_ are FORTRAN routines. In the source code, they do not have underscores at the end of their names; when the FORTRAN compiler compiles them, it inserts an underscore, and a C program must include this underscore to access the FORTRAN code. That's just a feature of how most FORTRAN compilers work on UNIX. */ int c1_ ( char dir[64] ); void c2_ ( int a[ARRSIZE][ARRSIZE] ); void for1_ ( int a[ARRSIZE][ARRSIZE] ); void for2_ ( int *int_val, float *real_val, float *complex_val, double *d_val ); void for3_ ( void ); void for4_ ( int a[ARRSIZE][ARRSIZE] ); void print_array ( int a[ARRSIZE][ARRSIZE] ); int main ( void ); void test01 ( void ); void test02 ( void ); void test03 ( void ); void test04 ( void ); int main ( void ) { /* Introduction */ printf ( "\n"); printf ( "MAIN:\n" ); printf ( " An example of a C/FORTRAN interface.\n"); printf ( " The main program is written in C.\n" ); printf ( " It calls FORTRAN routines, which in turn call C routines.\n" ); printf ( "\n"); test01(); test02(); test03(); test04(); printf ( "\n" ); printf ( "MAIN:\n" ); printf ( " Normal end of execution.\n" ); } void test01 ( void ) { /* Example 1: Pass an array to and from FORTRAN. */ /* ARRAY is declared in the FORTRAN routine as integer a(3,3) */ static int array[ARRSIZE][ARRSIZE] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; printf ( "\n" ); printf ( "TEST01:\n" ); printf ( " Define a 3 by 3 integer array in a C routine.\n" ); printf ( " Pass it to a FORTRAN routine for modification.\n" ); printf ( " Examine the returned value.\n"); printf ( "\n" ); printf ( "TEST01:\n" ); printf ( " Here is the initial value of ARRAY:\n"); print_array ( array ); printf ( "\n" ); printf ( "TEST01:\n" ); printf ( " Now we pass ARRAY to the FORTRAN routine FOR1 for processing.\n" ); for1_ ( array ); printf ( "\n" ); printf ( "TEST01:\n" ); printf ( " After return from FOR1, here is ARRAY:\n"); print_array ( array ); } void test02 ( void ) { /* Example 2: Pass numeric data to FORTRAN, where it is modified and returned. */ int int_val; float real_val; static float complex_val[2]; double d_val; int_val = 13; real_val = 42.85; complex_val[0] = 123.45; complex_val[1] = 6.789; d_val = 12345.006789; printf ( "\n" ); printf ( "TEST02:\n" ); printf ( " Pass numeric data to a FORTRAN routine, alter it, return it.\n" ); printf ( "\n" ); printf ( " Integer value = %d\n", int_val ); printf ( " Real value = %f\n", real_val ); printf ( " Complex value = %f + %f*i\n", complex_val[0], complex_val[1] ); printf ( " Double value = %f\n", d_val ); printf ( "\n" ); printf ( "TEST02\n" ); printf ( " Call FOR2 to modify these values.\n" ); for2_ ( &int_val, &real_val, complex_val, &d_val ); printf ( "\n" ); printf ( "TEST02:\n" ); printf ( " New values of data as modified by FOR2:\n" ); printf ( "\n" ); printf ( " Integer value = %d\n", int_val ); printf ( " Real value = %f\n", real_val ); printf ( " Complex value = %f + %f*i\n", complex_val[0], complex_val[1] ); printf ( " Double value = %f\n", d_val ); return; } void test03 ( void ) { printf ( "\n" ); printf ( "TEST03:\n" ); printf ( " Call a FORTRAN routine which calls a C routine.\n" ); printf ( " The C routine returns character data of some sort.\n" ); for3_ ( ); return; } void test04 ( void ) { /* Pass an array to a FORTRAN subroutine which passes it to a C routine. */ static int array[ARRSIZE][ARRSIZE] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; printf ( "\n" ); printf ( "TEST04:\n" ); printf ( " Pass an array to a FORTRAN routine.\n" ); printf ( " The FORTRAN routine passes the array to a C routine.\n" ); printf ( "\n" ); for4_ ( array ); return; } int c1_ ( char dir[64] ) { /* C1 gets the current working directory into an array of characters. If any problem occurs, return -1 You must use an array, not a pointer string. If a pointer string is used, only the first element will be passed back to FORTRAN. FORTRAN expects the space for the string to be previously allocated, therefore the C pointer string may cause problems. */ char *getcwd(); char *cwd; /* Store the current working directory in the string CWD. */ cwd = getcwd ( (char *) NULL, 64 ); if ( cwd == NULL ) { return (-1); } printf ( "\n" ); printf ( "C1:\n" ); printf ( " By calling the library routine GETCWD, we see that\n" ); printf ( " the current working directory is %s.\n", cwd ); /* Copy CWD to an array of single characters. It's easier for FORTRAN to deal with an array of characters than with a C string. */ strcpy ( dir, cwd ); return 0; } void c2_ ( int a[ARRSIZE][ARRSIZE] ) { /* C2 modifies an array. Since the array was passed from C to FORTRAN back to C, the indices are in the correct order. */ int abs(); int i; int j; printf ( "\n" ); printf ( "C2:\n" ); printf ( " The input value of ARRAY:\n"); print_array ( a ); for ( i = 0; i < ARRSIZE; i++ ) { for ( j = 0; j < ARRSIZE; j++ ) { if ( a[i][j] < 0 ) { a[i][j] = - a[i][j]; } a[i][j] = a[i][j] + 1; } } printf ( "\n" ); printf ( "C2:\n" ); printf ( " Modified value of ARRAY is:\n"); print_array ( a ); return; } void print_array ( int a[ARRSIZE][ARRSIZE] ) { int i; int j; for ( i=0; i < ARRSIZE; i++ ) { for ( j=0; j < ARRSIZE; j++ ) { printf ( "%4.0d ", a[i][j] ); } printf("\n"); } printf("\n"); return; }