1

I learned to call a C function from Fortran via the following link

Fortran/C Mixing : How to access dynamically allocated C array in Fortran?

and I have a "SIGSEGV" problem when changing the int to double in call_fc (corresponding code are also changed) when compiling with GNU compiler, while Intel compiler is fine.

The C code and Fortran code are as follows:

/// C function to be called from Fortran

#include "stdio.h"
#include "math.h"

void call_fc(double *(*x), int s)
{
    double *y = malloc(s*sizeof(double));
    int i;
    for(i=0; i < s; i++)
    {
        y[i]= sin((double)i);//(double)((i+1)*(i+1));
    }
    *x = y;
}

/// Fortran main routine to call C function

PROGRAM FORT_C
   use iso_c_binding
   IMPLICIT NONE

   interface
      subroutine call_fc(pX,s) bind(C,name='call_fc')
         import
         integer(c_int)     :: s
         type(c_ptr)        :: pX
      end subroutine
   end interface

   integer(c_int)                   :: i
   integer(c_int)                   :: s
   real(c_double), pointer          :: X(:)
   type(C_ptr)                      :: pX

   s=100

   call call_fc(pX,s)
   call c_f_pointer(pX,X,(/s/))

   do i=1,s
   write(*,*)  i, x(i)
   end do

END program

For GNU compiler (Thread model: posix gcc version 4.9.2 20150212 (Red Hat 4.9.2-6) (GCC) ), I use following commands to compile it:

gcc -c test.c -o testc.o
gfortran -c test.f90 -o testf.o
gfortran testc.o testf.o -o testg.x
./testg.x

Image_Output_Calling_C_From_Fortran_GNU_compiler

By the way, the commands with Intel compiler are:

icc -c test.c -o testc.o
ifort -c test.f90 -o testf.o
ifort testc.o testf.o -o testi.x
./testi.x

Please help me with the correct options for GNU compiler, Or modify the programs to be accepted by both compilers. Thank you very much!

After correction

/// test.c

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

void call_fc(double *(*x), int s)
{
    double *y = malloc(s*sizeof(double));
    int i;
    for(i=0; i < s; i++)
    {
        y[i]= sin((double)i);
    }
    *x = y;
}

/// test.f90

PROGRAM FORT_C
   use iso_c_binding
   IMPLICIT NONE

   interface
      subroutine call_fc(pX,s) bind(C,name='call_fc')
         import
         integer(c_int),value :: s
         type(c_ptr)          :: pX
      end subroutine
   end interface

   integer(c_int)           :: i
   integer(c_int)           :: s
   real(c_double), pointer  :: X(:)
   type(C_ptr)              :: pX

   s = 10
   call call_fc(pX,s)
   call c_f_pointer(pX,X,(/s/))

   do i=1,s
      write(*,*)  i, x(i)
   end do

END program
Community
  • 1
  • 1

1 Answers1

1

There are multiple problems in the program. First is just a C one. Do you disable compiler warnings? My gcc complains that

> gfortran value.c value.f90
value.c: In function ‘call_fc’:
value.c:7:17: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
     double *y = malloc(s*sizeof(double));
             ^

This may not cause a crash on one computer but may easily cause it elsewhere.

You should include

#include <stdlib.h>

The other includes should also be in angle brackets <> and not in "" because they are standard C headers.

The Fortran part has the problem in the interface. You want

integer(c_int), value :: s

because the C function expects the arguments by value. The other argument does not have value because it is a pointer passed by reference and C has a pointer to a pointer.