I was recently trying to pass data back from C to FORTRAN for a program I'm using. While I found plenty of stuff on sending data from FORTRAN to C, but when I tried to use it in reverse, I got some gibberish. Below is my solution and here is a gunzip'd tarball of all the files involved.
mapsetup.c: the meat of this little entry
/* mapsetup.c -- Miles V. Aronnax * Functions to read, store and return values from the mapping table. */ #include <stdlib.h> #include <stdio.h> #include <string.h> // Structure for storing the parsed mapping table. struct nucleus_mapping_table { char nucleus_name[32]; float ground_state_energy; char storage_location[200]; } numap[3]; // Get nucleus name void mapget_name(int *nucounter, char *name) { int idx = *nucounter - 1; strcpy(name, numap[idx].nucleus_name); } // Get absolute ground state energy void mapget_eabs(int *nucounter, float *eabs) { int idx = *nucounter - 1; *eabs = numap[idx].ground_state_energy; } // Get nucleus storage folder void mapget_nloc(int *nucounter, char *nloc) { int idx = *nucounter - 1; strcpy(nloc, numap[idx].storage_location); } // Read values from a table row (line) and load into numap. void parse_table_row(int idx, char *line) { char *afield; afield = strtok(line, "\t"); // first column: number strcpy( numap[idx].nucleus_name, strtok(NULL, "\t") ); numap[idx].ground_state_energy = atof(strtok(NULL, "\t")); strcpy( numap[idx].storage_location, strtok(NULL, "\n") ); printf(" Stored: {%s, %f, %s} --> numap[%i]\n", numap[idx].nucleus_name, numap[idx].ground_state_energy, numap[idx].storage_location, idx); } // Read values from mapping table fspec into array numap. void read_mapping_table(char *fspec) { printf(" In read_mapping_table()...\n"); int idx=0; char line[100]; FILE *mapfile; // Open the mapping file. printf(" fopen(%s, r)\n", fspec); mapfile = fopen(fspec, "r"); if( mapfile==NULL ) { printf("Couldn't open mapfile.\n"); exit(0);} // Read the file one line at a time. while(!feof(mapfile)) { fgets(line, 100, mapfile); //printf("line=[%s]", line); if( line != "" && strlen(line) > 5 ) { printf(" Parsing table row %i...\n", idx); parse_table_row(idx, line); idx++; } } // Close file and exit subroutine. fclose(mapfile); }
test.f: how to call the C functions from FORTRAN
! Fortran test: calling c functions from mapsetup.c ! Miles V. Aronnax program test_this integer idx real ground_state_energy character*32 nucleus_name character*200 storage_location write(*,*) "Begin program test_this..." ! Read nuclei.map file into c array struct numap. ! Note addition of null character to string. C expects strings ! to be null terminated...fortran doesn't do that automatically. call read_mapping_table("nuclei.map"//CHAR(0)) write(*,*) "Call read_mapping_table done." ! Clear the fortran varables before trying to get values from c functions. ! This prevents strings from containing random data if the string length ! is less than the variable size. ground_state_energy = 0 nucleus_name = "" storage_location = "" write(*,*) "Reading values in fortran using c functions..." ! There are 3 rows of the numap table. ! I was just lazy here. I could have made the numap table ! dynamically allocated and then had a function to return ! the number of entries, but I didn't so...*shrug* idx = 1 do while (idx < 4) call mapget_name(idx, nucleus_name) call mapget_eabs(idx, ground_state_energy) call mapget_nloc(idx, storage_location) write(*,*) " Nucleus ", idx, " = {", & &trim(nucleus_name), ", ", & &ground_state_energy, ", ", & &trim(storage_location), "}" idx = idx + 1 enddo write(*,*) "End program test_this." end program test_this
Makefile: instructions to compile
# Mapping Table Test Makefile -- Miles V. Aronnax # Need CC=a c compiler, FC=a fortran 90+ compiler CC=gcc FC=gfortran42 default: mapsetup.o test.f ${FC} -ffree-form -fno-underscoring -o test test.f mapsetup.o # nm mapsetup.o is informational. It dumps the list of symbols in the .o file. mapsetup.o: mapsetup.c ${CC} -c mapsetup.c nm mapsetup.o clean: rm -f *.o *.mod *.core test
nuclei.map: the input file
1 47Ca -406.05400 /path/to/47Ca 2 48Ca -415.99000 /path/to/48Ca 3 49Ca -421.13687 /path/to/49Ca
Attachment | Size |
---|---|
maptable.tar_.gz | 1.86 KB |