0

I have a problem where I am calling a C function using from a FORTRAN program.

I situation is I am passing a variable's address as a parameter from FORTRAN and using it in C and I return the same variable after doing some computation.

In the C function when I declare the parameter as a pointer then I am able to get the required value of the variable in the FORTRAN program but it shows a Segmentation Fault.

But whereas if I declare the parameter as a normal variable then I am unable to pass the value back to FORTRAN

An example would be

File: fortran_prog.f

program test
    integer :: a=10
    
    call c_func(a)
    write(*,*) a
end program test

File: c_prog1.c

#include<stdio.h>
void c_func_(int *a) {
    int *b = 100;
    *a = *b
}

In this case I get the value of 'a' as 100 but it also shows Segmentation Fault after the FORTRAN program exits.

But if I change the C program like this

File: c_prog2.c

#include<stdio.h>
void c_func_(int *a) {
    int b = 100;
    a = &b;
}

In this case I get the value of a as 0 in the FORTRAN program. I couldn't find out the reason for this behavior

The C prog is compiled with gcc and FORTRAN program with gfortran. When used GDB to back trace I got the error message

Program received signal SIGSEGV, Segmentation fault.

0x00000000 in ?? ()

Any help/suggestion would be appreciated.

PS: The above examples are merely replicating the actual program's code.

Community
  • 1
  • 1
arunr
  • 59
  • 5
  • 1
    (a) Why are you using a `.f` file yet using free-form (which is a Fortran 90 feature)? (b) Why are you *not* using the [ISO_C_BINDING](http://gcc.gnu.org/onlinedocs/gfortran/ISO_005fC_005fBINDING.html) module? (c) How are you actually compiling the two files? – Kyle Kanos Dec 20 '13 at 14:12
  • As Kyle Kanos suggests, the modern way to interface Fortran & C is to use the ISO_C_BINDING. There are many examples under that tag: http://stackoverflow.com/questions/tagged/fortran-iso-c-binding. One from several days ago: http://stackoverflow.com/questions/20650227/unable-to-pass-array-from-fortran-to-c -- which is a previous question that you asked. – M. S. B. Dec 20 '13 at 15:34
  • @M.S.B. The reason for my not using ISO_C_BINDING is that in place of int I have some structure variables that I have to use and the implementation of those structures is not known. Moreover, I have implemented for two different structures from a library. For one I am able to achieve the reqd data in Fortran prog, but for the other I get the reqd data but shows seg fault. If I comment one of the assignment I don't get the error and I am able to pass the value. The error occurs when both the structures are used and assigned. Also the implementation of assigning these 2 structures is same – arunr Dec 23 '13 at 06:45
  • @anur. The Fortran ISO_C_BINDING provides the capability, with certain limitations, of matching C structures. See "Derived Types and struct" in the "Mixed-Language Programming" Chapter of the gfortran manual or https://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlf101a.doc%2Fxlflr%2Finterop-types.htm. If the C structure satisfies the requirements of the ISO_C_Binding, you don't have to know the implementation ... by specifying the ISO_C_Binding, the Fortran compiler will match the C compiler's implementation. – M. S. B. Dec 23 '13 at 07:36
  • The solution that I found for the above problem is that the compiler needed the option -O2. After using the option I was able to execute the program with the need for ISO_C_Binding module. Thanks to @M.S.B's comment for the question http://stackoverflow.com/questions/17831110/segmentation-fault-core-dumped-in-fortran?rq=1 – arunr Dec 23 '13 at 11:45

2 Answers2

0

Try:

#include<stdio.h>
void c_func_(int *a) {
    int b = 100;
    *a = b;
}

In the second example, you are setting the value of a to an invalid address. Presumably, in code you have elided from the example, you later reference that in the C function and generate the segfault. To assign to the value of a, you just need a dereference on the LHS of the assignment.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
0

void c_func_(int *a) { int *b = 100; *a = *b }

you don't mean int *b =100, this means create a pointer to an int and point it to the memory location 100; I'd atleast assume you mean

void c_func_(int *a) { int b = 100; *a = b }

or in your sample you are referencing some unknown value in your stack...

void c_func_(int *a) { int b = 100; a = &b; }

because b is stored on the stack and &b points to b which is on the stack then you set a to point to the address of a, however you don't change the contents of a hence the result is not changed. You should be able to find the documentation on how C & Fortran can be combined in your environment. I'd assume that's why you are getting some runtime errors if it was me I'd prefer the following API

int c_func_(int a) { int b = 10; return a * b; }

I'd recommend reading K&R (http://en.wikipedia.org/wiki/The_C_Programming_Language) or some other book that explains pointers, stacks etc....

Angus Connell
  • 419
  • 3
  • 6