4

我最近遇到了一种情况,我想从 Fortran 调用一个 C 函数,因为一个有用的 C 代码片段。为了方便数组操作,我也希望能够使用数组参数调用这个函数,但它只接受标量参数。

在 Fortran 中,当然可以简单地声明一个过程来elemental实现这一点,并且可以声明一个 C 过程的接口bind(C)。但是,由于 C 没有基本过程的概念,因此 Fortran (2008) 标准排除了这种组合:

C1246 基本过程不应具有 BIND 属性。

那么,这个功能可以在 Fortran 中实现吗?

4

1 回答 1

7

经过一番搜索,我发现使用 Fortran 2003 和iso_c_binding内部模块,这既可行又非常简单;我想我应该在这里记录一下。具有该bind属性的接口仍然可以存在pure,因此可以在本身的 Fortran 过程中引用它elemental

以下是 C99 宏的简短示例,isnan如果其参数为 NaN,则返回非零整数值。当然,这也可以用于任何没有副作用的用户定义的 C/C++ 函数。

elemental function isnan(val)
  use, intrinsic :: iso_c_binding
  implicit none

  real(c_double), intent(in) :: val
  logical(c_bool) :: isnan

  interface
    pure function isnan_C(val) bind(C, name = 'isnan')
      import
      ! Pass the parameter by value:
      real(c_double), value, intent(in) :: val
      integer(c_int) :: isnan_C
    end function
  end interface

  isnan = isnan_C(val) /= 0_c_int
end function

使用具有一些 NaN 值的数组的示例输出:

program main
  use, intrinsic :: iso_c_binding
  implicit none

  real(c_double) :: nan(2,2) = 0.
  nan(:,2) = nan(1,1)/0.

  write(*,'(4F6.2 / 4L6)') nan, isnan(nan) ! Output: 0.00 0.00  NaN  NaN
                                           !            F    F    T    T
end program
于 2012-12-07T13:31:17.747 回答