【问题标题】:About using Fortran function in C with iso_c_binding关于在 C 中通过 iso_c_binding 使用 Fortran 函数
【发布时间】:2016-11-23 11:53:10
【问题描述】:

我花了几天时间学习 Fortran 的 C 互操作性,以便从 C 调用 Fortran 函数 DLL。 在这里我找到了这个链接: Use Fortran-code in C

我尝试像这样创建一个 Fortran DLL,而我的编译器是 Intel Fortran 编译器:

module integration
  implicit none

contains

  function Integrate(func, a,b, intsteps) result(integral)
!DEC$ ATTRIBUTES DLLEXPORT :: Integrate
    interface
      real function func(x)
        real, intent(in) :: x
      end function func
    end interface

    real :: integral, a, b
    integer :: intsteps
    intent(in) :: a, b, intsteps
    optional :: intsteps

    real :: x, dx
    integer :: i,n
    integer, parameter :: rk = kind(x)

    n = 1000
    if (present(intsteps)) n = intsteps

    dx = (b-a)/n

    integral = 0.0_rk
    do i = 1,n
      x = a + (1.0_rk * i - 0.5_rk) * dx
      integral = integral + func(x)
    end do

    integral = integral * dx
  end function

end module integration


    real(c_float) function wrapper_integrate(func, a, b, intsteps) result(integral) bind(C, name='integrate')
  use iso_c_binding
  use integration

 interface
    function iFunc(x) bind(C)
      use, intrinsic :: iso_c_binding
      real(c_float) :: iFunc
      real(c_float), intent(in) :: x
    end function iFunc
  end interface

  type(C_FUNPTR), INTENT(IN), VALUE :: func
  real(c_float) :: a,b
  integer(c_int),intent(in) :: intsteps
  optional :: intsteps

  procedure(iFunc),pointer :: myfunc
  call c_f_procpointer(func, myfunc)

  if (present(intsteps)) then
    integral = Integrate(myfunc,a,b,intsteps)   <==error #8128
  else
    integral = Integrate(myfunc,a,b)          <==error #8128
  endif

end function wrapper_integrate

当我构建 DLL 时,错误显示如下

error #8128: The BIND attribute of the associated actual procedure differs from the BIND attribute of the dummy procedure.   [MYFUNC]

代码中表示的错误行,看起来myfunc 不等于模块集成中定义的func。也许我可以使用iso_c_binding 来修改模块integration

有时某些 Fortrans 函数有许多参数要在函数中分配和使用,在 Fortran 中使用 iso_c_binding 并不容易。那么如何解决MYFUNC中的错误呢?

【问题讨论】:

  • Integrate 中的虚拟程序具有bind 属性;函数指针myfunc 是实际参数,它具有给定的接口iFunc,它没有bind 接口。
  • 是的!我忘了!现在我可以导出 Fortran Dll。
  • 感谢您编辑我的问题,使它变得整洁!

标签: visual-c++ fortran intel-fortran fortran-iso-c-binding


【解决方案1】:

如果一个虚拟过程有一个显式接口,那么它的特性必须与实际过程的特性相同,除了一些在这里不相关的东西。

过程的特征包括它是否具有BIND属性。

为了使特性保持一致,您可以使用一个没有 BIND(C) 的中间过程来调用您提供的 BIND(C) 过程。

例如,为了避免关于 c_float 和 c_int 是否指定默认实数和整数类型的假设而进行了一些其他更改:

function wrapper_integrate(func, a, b, intsteps)  &
    result(integral) bind(C, name='integrate')
  use iso_c_binding
  use integration
  implicit none

  interface
    function func(x) bind(C)
      use, intrinsic :: iso_c_binding
      implicit none
      real(c_float), intent(in) :: x
      real(c_float) :: func
    end function func
  end interface

  real(c_float), intent(in) :: a,b
  integer(c_int), intent(in), optional :: intsteps
  real(c_float) :: integral

  real :: local_a, local_b
  integer :: local_intsteps

  local_a = a
  local_b = b
  if (present(intsteps)) then
    local_intsteps = intsteps
    integral = Integrate(local_func, a, b, local_intsteps)
  else
    integral = Integrate(local_func, a, b)
  end if
contains
  function local_func(x)
    real, intent(in) :: x
    real :: local_func

    real(c_float) :: local_x

    local_x = x
    local_func = func(local_x)
  end function local_func
end function wrapper_integrate

请注意,可互操作过程中存在可选参数是 Fortran 2015 的一项功能。

【讨论】:

  • 谢谢!我需要检查一下!
  • 对了,.NET Framework中可以调用Intel Fortran?
  • bind(C, name='integrate') 应该是 bind(C, name='wrapper_integrate'),它有效!而且这个方法对我很有帮助。
  • 绑定标签的名称取决于你调用的C函数。
  • 好吧,如果我想将一个数组传递给 local_func?怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-25
  • 2017-07-20
相关资源
最近更新 更多