在C中使用Fortran函数会导致启动时出现段错误

时间:2018-08-02 05:16:23

标签: c gcc fortran gfortran fortran-iso-c-binding

我尝试使用iso_c_binding实现Fortran派生的C型绑定的基本示例。

circle.f90

module class_circle

use iso_c_binding

implicit none
private
public :: Circle, init_Circle

real(c_double), parameter :: pi = 3.1415926535897932384626433832795

type, bind(C) :: Circle
   real(c_double) :: radius = 1
   real(c_double) :: area
end type Circle

contains

type(Circle) function init_Circle(r) bind(C, name='init_Circle')
   implicit none
   real(c_double), intent(in) :: r

   init_Circle%radius = r
   init_Circle%area = pi * r * r
end function init_Circle

end module class_circle

main_c.c

#include <stdio.h>

struct circle {
    double radius, area;
};

struct circle* init_Circle(double* r);

int main() {
    double r = 10;
    struct circle* c = init_Circle(&r);
    double area = c->area;
    printf("%lg", area);
    return 0;
}

编译:

gcc -g -c main_c.c -o main_c.o
gfortran -g -c circle.f90
gcc -g main_c.o circle.o -o main_c

结果:

[1]    99081 segmentation fault  ./main_c

1 个答案:

答案 0 :(得分:2)

您的C函数原型说该函数返回一个指向结构的指针

struct circle* init_Circle(double* r);

但是Fortran函数直接返回一个结构

type(Circle) function init_Circle(r) bind(C, name='init_Circle')

您必须使这一点保持一致。

还要注意@evets的注释,无论3.1415926535897932384626433832795有多少位数,它都只是一个精度数字。借助value属性,可以简化C中的函数及其调用。

module class_circle

use iso_c_binding

implicit none
private
public :: Circle, init_Circle

real(c_double), parameter :: pi = 3.1415926535897932384626433832795_c_double

type, bind(C) :: Circle
   real(c_double) :: radius = 1
   real(c_double) :: area
end type Circle

contains

type(Circle) function init_Circle(r) bind(C, name='init_Circle')
   implicit none
   real(c_double), value :: r

   init_Circle%radius = r
   init_Circle%area = pi * r * r
end function init_Circle

end module class_circle

#include <stdio.h>

struct circle {
    double radius, area;
};

struct circle init_Circle(double r);

int main() {
    double r = 10;
    struct circle c = init_Circle(r);
    double area = c.area;
    printf("%lg", area);
    return 0;
}

> gfortran circle.f90 main_c.c
> ./a.out 
314.159