0

I'm having troubles to pass a string from Fortran to C. The C code passes a string that contains a filepath to a Fortran function. The function reads in the file and should return a two-characters string.

Here is my C code

#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <sys/time.h>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <time.h>
#include <ctype.h>
using namespace std;

extern "C" void read_id_type_(char *file_path, char *id_type, size_t *path_len_file);

int main(int argc, char **argv) {

char path[500],id_type[2];
char *dir_path, *file_path;
dir_path=path;
size_t path_len=strlen(dir_path);

file_path=strcat(path,"/rnspar_mpt1.dat");
size_t path_len_file=strlen(file_path);

read_id_type_(file_path,id_type,&path_len_file);
 printf("id_type is %s\n",id_type);

 return EXIT_SUCCESS ;
 }

Here is my Fortran function

 integer function read_id_type(filename,id_type,path_len) 
 implicit none

 integer :: nrg, nrf, nrf_deform, nrgin,path_len
 character(400) :: filename
 character(2) ::  id_type,EQ_point

 filename=filename(1:path_len)
 write(*,*),"Reading file", filename

 open(unit = 1,file = trim(filename), status='old')
 read(1,'(4i5)') nrg
 read(1,'(4i5)') nrf
 read(1,'(2i5,2(3x,a2))') nrf_deform, nrgin, id_type, EQ_point
 close(1)
 print *,"Id_type=",id_type
 read_id_type = 0
 end function read_id_type

The output is:

Id_type=IR    (From the Fortran side)

id_type is IRV2?      (From the C side)

The output, in the C code, should be only the first two characters. Any help would be much appreciated

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Milton
  • 13
  • 4
  • Maybe http://stackoverflow.com/q/19913383/577108 and http://stackoverflow.com/q/9972743/577108 can give you an idea. – haraldkl Jul 05 '16 at 18:31
  • By the way, note that ``, ``, `` and `` are C++ headers, and `using namespace std;` is a C++ statement. So this code won't compile as C. Although the main code is pure C style, it will only compile as C++. – Cheers and hth. - Alf Jul 05 '16 at 18:37
  • 1
    There is an example of passing a string from C to Fortran at http://stackoverflow.com/questions/8207997/calling-a-fortran-subroutine-from-c . I suggest studying that to understand the difference between C and Fortran strings. Next step: further study of the ISO C Binding to add a return argument. There are many examples on Stack Overflow. – M. S. B. Jul 05 '16 at 18:45

1 Answers1

0

Instead of

id_type[2]

make that at least

id_type[3]

and set the 3rd character (at index 2) to integer 0 after the call to the Fortran routine, otherwise it won't be a zero-terminated string that C understands.


Since the current code tries to output a non-zero-terminated string it accesses memory beyond the array and has formally Undefined Behavior.

With UB anything or nothing or possibly what you expect can happen.

You just got some weird extra characters.


The string displays correctly in Fortran because you've specified its length there,

character(2) ::  id_type

There's not really a corresponding feature in C, but in C++ you could use a std::string of length 2 and pass its buffer to the Fortran routine,

std::string id_type( 2, ' ' );

//...
read_id_type_( file_path, &id_type[0], &path_len_file );
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • I've been trying id_type[3] and the output is pretty much the same: id_type is IR??h – Milton Jul 05 '16 at 18:26
  • If you really set the 3rd character to integer 0, then C output functions won't display more than the 2 first characters. So, try again. ;-) – Cheers and hth. - Alf Jul 05 '16 at 18:35
  • Thanks a lot! the solution turned out to be simpler. The key point is to null terminate the string. I'm using `id_type[2]='\0'; ` and it works just fine! – Milton Jul 05 '16 at 21:05