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