c - 用于数组和标量的 Fortran 到 C 接口(interface)

标签 c arrays fortran scalar fortran-iso-c-binding

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

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

我想编写一个适用于数组(任何维度)和标量的 Fortran 接口(interface)。
我的 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

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

为什么该接口(interface)不适用于 cset( array2d, size(array2d) ),但适用于 cset_array( array2d, size(array2d) )调用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)

有没有更“正确”的方式来编写这样的界面?以这种方式传递标量可以吗?

谢谢您并致以亲切的问候。

相关:
Passing a two dimentional array from Fortran to C
Passing both scalars and arrays (of any dimensions) from Fortran to C

最佳答案

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

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

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

关于c - 用于数组和标量的 Fortran 到 C 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59660602/

相关文章:

c++ - fork 一次然后在不同的过程中使用线程?

c - 将字符串数组分配给字符串指针数组

c - C程序运行时出现错误

javascript - 将每个单词推送到一个数组

javascript - 比较两个数组的 Angular 并对其进行循环

fortran - 为什么 Fortran 中有一个隐含的 SAVE 属性?

c - 在使用 'IF' 语句前进后,有没有办法返回?

c - Realloc 在第二个循环中停止程序

java - 如何使用java onclick shuffle数组

fortran - Fortran 中 "stop"和 "exit"有什么区别?