在 C 中使用 Fortran 函数会导致启动时出现段错误
Using of Fortran function in C causes seg fault on start up
我尝试使用 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
你的 C 函数原型说函数 returns 一个指向结构的指针
struct circle* init_Circle(double* r);
但是 Fortran 函数 returns 直接一个结构
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
我尝试使用 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
你的 C 函数原型说函数 returns 一个指向结构的指针
struct circle* init_Circle(double* r);
但是 Fortran 函数 returns 直接一个结构
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