Fortran 到 C 的接口:为什么正确操作会搞砸一切?
Fortran to C interface: Why does doing it right mess everything up?
关于 Fortran/C 接口,我还有很多东西要学习。在我正在使用的玩具代码中,我使用 C 为 Fortran 分配一个双精度数组(实际上是指针):
double precision, pointer :: arr(:)
type(C_PTR) :: p
integer :: L=50000
p = alloc_for_fortran(L)
call c_f_pointer(p, arr, [L])
(alloc_for_fortran
是我写的一个 C 函数。似乎工作正常。我可以展示它,但我想我会尽量避免不相关的代码,以使这个 post 尽可能短我可以。)
我有一个简单的 C 函数,它只给出数组的元素:
void examine(double *arr, int *whichone) {
printf("contents: %lf\n", arr[*whichone-1]);
}
如果我不在 Fortran 代码中定义 接口,这很好用。例如,这段代码
arr(1) = 5.3
examine(arr,1)
给出输出:
contents: 5.300000
现在我为 examine
定义一个接口,就像我“应该”:
interface
subroutine examine(arr, i) bind(C, name="examine")
use iso_c_binding
double precision, pointer :: arr(:)
integer :: i
end subroutine
end interface
现在输出不正确:
contents: 0.000000
谁能告诉我我做错了什么?
这是您的操作方法。除非您提供 minimal, reproducible example 否则很难说更多。显示的主要错误是试图将 Fortran 指针传递给 C 指针,当标准 Fortran 参数机制足够时,以及将 C 虚拟参数声明为假定形状数组,而你应该使用假定大小,因为 C 不这样做支持更高级的 Fortran 功能
ian@eris:~/work/stack$ cat examine.c
#include <stdio.h>
void examine(double *arr, int *whichone) {
printf("contents: %lf\n", arr[*whichone-1]);
}
ian@eris:~/work/stack$ cat use_examine.f90
Program use_examine
Use iso_c_binding, Only : c_double, c_int
Implicit None
Interface
Subroutine examine( arr, i ) bind( C, name = 'examine' )
Use iso_c_binding, Only : c_double, c_int
Implicit None
Real ( c_double ), Dimension( * ), Intent( In ) :: arr
Integer( c_int ) , Intent( In ) :: i
End Subroutine examine
End Interface
Real( c_double ), Pointer, Dimension( : ) :: a
Allocate( a( 1:2 ) )
a( 1 ) = 5.3_c_double
Call examine( a, 1_c_int )
End Program use_examine
ian@eris:~/work/stack$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ian@eris:~/work/stack$ gcc -c -Wall -Wextra -std=c99 examine.c
ian@eris:~/work/stack$ gfortran -c -Wall -Wextra -fcheck=all -std=f2008 use_examine.f90
ian@eris:~/work/stack$ gfortran use_examine.o examine.o
ian@eris:~/work/stack$ ./a.out
contents: 5.300000
关于 Fortran/C 接口,我还有很多东西要学习。在我正在使用的玩具代码中,我使用 C 为 Fortran 分配一个双精度数组(实际上是指针):
double precision, pointer :: arr(:)
type(C_PTR) :: p
integer :: L=50000
p = alloc_for_fortran(L)
call c_f_pointer(p, arr, [L])
(alloc_for_fortran
是我写的一个 C 函数。似乎工作正常。我可以展示它,但我想我会尽量避免不相关的代码,以使这个 post 尽可能短我可以。)
我有一个简单的 C 函数,它只给出数组的元素:
void examine(double *arr, int *whichone) {
printf("contents: %lf\n", arr[*whichone-1]);
}
如果我不在 Fortran 代码中定义 接口,这很好用。例如,这段代码
arr(1) = 5.3
examine(arr,1)
给出输出:
contents: 5.300000
现在我为 examine
定义一个接口,就像我“应该”:
interface
subroutine examine(arr, i) bind(C, name="examine")
use iso_c_binding
double precision, pointer :: arr(:)
integer :: i
end subroutine
end interface
现在输出不正确:
contents: 0.000000
谁能告诉我我做错了什么?
这是您的操作方法。除非您提供 minimal, reproducible example 否则很难说更多。显示的主要错误是试图将 Fortran 指针传递给 C 指针,当标准 Fortran 参数机制足够时,以及将 C 虚拟参数声明为假定形状数组,而你应该使用假定大小,因为 C 不这样做支持更高级的 Fortran 功能
ian@eris:~/work/stack$ cat examine.c
#include <stdio.h>
void examine(double *arr, int *whichone) {
printf("contents: %lf\n", arr[*whichone-1]);
}
ian@eris:~/work/stack$ cat use_examine.f90
Program use_examine
Use iso_c_binding, Only : c_double, c_int
Implicit None
Interface
Subroutine examine( arr, i ) bind( C, name = 'examine' )
Use iso_c_binding, Only : c_double, c_int
Implicit None
Real ( c_double ), Dimension( * ), Intent( In ) :: arr
Integer( c_int ) , Intent( In ) :: i
End Subroutine examine
End Interface
Real( c_double ), Pointer, Dimension( : ) :: a
Allocate( a( 1:2 ) )
a( 1 ) = 5.3_c_double
Call examine( a, 1_c_int )
End Program use_examine
ian@eris:~/work/stack$ gcc --version
gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ian@eris:~/work/stack$ gcc -c -Wall -Wextra -std=c99 examine.c
ian@eris:~/work/stack$ gfortran -c -Wall -Wextra -fcheck=all -std=f2008 use_examine.f90
ian@eris:~/work/stack$ gfortran use_examine.o examine.o
ian@eris:~/work/stack$ ./a.out
contents: 5.300000