2

I'm trying to call a global string variable which is defined in a Fortran subroutine, in C. the C code is Cfile.c:

#include <stdio.h>

typedef struct {
        int length;
        char* string;
} fstring;

extern fstring stringf_;
void fortfunc_();

int main() {
        fstring stringC = stringf_;
        stringC.string[stringC.length-1] = '\0';
        printf("%s \n",stringC.string);
        return 0;
}

and FORTRAN code is Ffile.f:

subroutine fortfunc()
  
        character*30 string
        common/stringF/ string
        string = 'this is a string in FROTRAN77'

return
end

it compiles with:

gcc -c Cfile.c
gfortran -c -std=legacy Ffile.f
gfortran -c file.out -std=legacy Cfile.o Ffile.o

but when running I get the segmentation fault. I do not understand when I'm violating the memory boundaries though.

My operating system is:

Linux ubuntu 4.15.0-39-generic #42-Ubuntu SMP Tue Oct 23 15:48:01 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

and my compilers are:

GNU Fortran (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0

gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0

I would appreciate if you could help me know where is my mistake and how I can solve it? other solutions to define a global variable in Fortran and then calling it in C are also welcomed.

Community
  • 1
  • 1
Foad S. Farimani
  • 12,396
  • 15
  • 78
  • 193
  • verify that `stringC.length` is valid (>0) before using it as index. – Aganju Dec 01 '18 at 03:09
  • @Aganju good point. I had already figured out that the returns 0 and that causes the segfault. but the questions remains then how can I pass a string from FORTRAN to C. you see more examples [here](https://github.com/Foadsf/Cmathtuts/tree/dev/A_fortran). – Foad S. Farimani Dec 01 '18 at 09:28
  • Even better learn how to spell Fortran and search for "pass a string from Fortran to C" – Ian Bush Dec 01 '18 at 15:12
  • Hold on a second, generally speaking, local variables, unless static in C, don't have any scope outside of the function... In that sense, it would be a good idea to test the variable in the Fortran module, in a test module I think. See if you can print it there before trying to get it from the C function. Many thanks for the update! – Krassi Em Dec 01 '18 at 17:30
  • Changing the code to "typedef struct { char string[ 30 ]; } fstring;" and "stringC.string[ 29 ] = '\0';" works on my computer (<-- I think the common block contains raw characters rather than the pointer to them) – roygvib Dec 01 '18 at 20:18

1 Answers1

2

Based on the comments I got here and on Reddit, I now have a code which works. The C code:

#include <stdio.h>

typedef struct {
    char s[30];
} fstring;

extern fstring stringf_;

int main() {
    fstring stringc = stringf_;
    stringc.s[29] = '\0';
    printf("%s\n",stringc.s);
    return 0;
}

and FORTRAN code:

        BLOCK DATA

                CHARACTER*30 S
                COMMON /STRINGF/ S
                DATA S /'this is a string in FROTRAN77'/

        end

The segfault was happening because the passed stringC.length value is zero. It means unlike the example I was following here when calling a string from the FORTRAN side it does not pass the length as an integer!

Foad S. Farimani
  • 12,396
  • 15
  • 78
  • 193