数组和标量的 Fortran 到 C 接口

Fortran to C interface for arrays and scalars

我正在学习如何将 Fortran 与 C 接口。我编写了简单的 C 代码,将所有数组值设置为 1:

#include <stdlib.h>
void cset( int *array, int size ) {
  for (size_t i = 0; i < size; i++) {
    array[i] = 1;
  }
  return;
}

我想编写一个 Fortran 接口来处理数组(任意维度)和标量。
我的 Fortran 代码:

program main
  use iso_c_binding
  implicit none

  interface cset
    ! Interface for arrays.
    subroutine cset_array( array, size ) bind( C, NAME="cset" )
      import
      integer(C_INT), intent(inout)     :: array(*)
      integer(C_INT), value, intent(in) :: size
    end subroutine cset_array

    ! Interface for scalars. NOTE: Fortran values are passed by reference (so this should work)
    subroutine cset_scalar( scalar, size ) bind( C, NAME="cset" )
      import
      integer(C_INT), intent(inout)     :: scalar
      integer(C_INT), value, intent(in) :: size
    end subroutine cset_scalar

  end interface cset

  integer :: scalar = 0
  integer :: array(3) = 0
  integer :: array2d(3,3) = 0

  call cset( scalar, 1 )
  print *, scalar

  call cset( array, size(array) )
  print *, array

  ! Does not work???
  ! call cset( array2d, size(array2d) )

  ! But works for
  call cset_array( array2d, size(array2d) )
  ! OR call cset( array2d(1,1), size(array2d) )
  print *, array2d

end program main

这适用于标量和一维数组。

为什么界面不适用于 cset( array2d, size(array2d) ),但适用于 cset_array( array2d, size(array2d) )call cset( array2d(1,1), size(array2d) )?在第一种情况下,我收到以下错误 (gfortran-7.4):

call cset( array2d, size(array2d) )
                                  1
Error: There is no specific subroutine for the generic ‘cset’ at (1)

有没有更'proper'的方式来写这样的接口?以这种方式传递标量是否可以?

谢谢你和亲切的问候。

相关:
Passing a two dimentional array from Fortran to C

您不能使用假定大小的数组 (dimension(*)) 来允许将相同的特定过程用于多个等级(维度)的数组。由于 TKR 规则(类型、种类、等级),所有特定程序仅适用于一个等级。如果您尝试将不同级别的数组传递给通用过程,即使可以将数组直接传递给特定过程,特定过程也不会被识别。

我知道的唯一解决方案是为每个等级分别制作特定的程序接口。

subroutine cset_array1( array, size ) bind( C, NAME="cset" )
  import
  integer(C_INT), intent(inout)     :: array(*)
  integer(C_INT), value, intent(in) :: size
end subroutine cset_array1

subroutine cset_array2( array, size ) bind( C, NAME="cset" )
  import
  integer(C_INT), intent(inout)     :: array(1,*)
  integer(C_INT), value, intent(in) :: size
end subroutine cset_array2

如果你只有一个程序可以接受任何东西,比如 MPI 程序,那么可以使用特定的编译器

!$GCC attributes no_arg_check

或与!$DEC

相同