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 |