加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在C中使用Fortran代码

发布时间:2020-12-16 09:58:03 所属栏目:百科 来源:网络整理
导读:我尝试在C中使用fortran-routine,但是我没有工作.我不知道我犯了什么错误.这里是我的Fortran代码,包括我想在C中使用的Integration-Module: module integration implicit nonecontains function Integrate(func,a,b,intsteps) result(integral) interface re
我尝试在C中使用fortran-routine,但是我没有工作.我不知道我犯了什么错误.这里是我的Fortran代码,包括我想在C中使用的Integration-Module:

module integration
  implicit none

contains

  function Integrate(func,a,b,intsteps) result(integral)

    interface
      real function func(x)
        real,intent(in) :: x
      end function func
    end interface

    real :: integral,b
    integer :: intsteps
    intent(in) :: a,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,intsteps) result(integral) bind(C,name='integrate')
  use iso_c_binding
  use integration

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

  real(c_float) :: a,b
  integer(c_int),intent(in) :: intsteps
  optional :: intsteps
  if (present(intsteps)) then
    integral = Integrate(func,intsteps)
  else
    integral = Integrate(func,b)
  endif

end function wrapper_integrate

和我的C代码:

#include <stdio.h>
#include <math.h>

float sin2(float x) {
  return sin(x) * sin(x);
}

float integrate(float(*func)(float),float a,float b,int intsteps);

int main() {
  float integral;
  integral = integrate(sin2,0.,1.,10000);
  printf("%f",integral);
  return 0;
}

如果我执行

g++ -c main.c
gfortran -c integration.f95
g++ main.o integration.o

我明白了

undefined reference to `integrate(float (*)(float),float,int)'

有谁知道如何处理这个?

解决方法

如果使用模块ISO_C_Binding,则可以直接将函数从C传递给Fortran作为函数指针C_FUNPTR.
有关详情,请参见 here.

在您的情况下,这将看起来像:

real(c_float) function wrapper_integrate(func,name='integrate')
  use iso_c_binding
  use integration

  abstract 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,intent(in) :: intsteps
  optional :: intsteps

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

  if (present(intsteps)) then
    integral = Integrate(myfunc,intsteps)
  else
    integral = Integrate(myfunc,b)
  endif

end function wrapper_integrate

显然,你的解决方案更优雅;-)

另请注意,Fortran通过引用传递变量(除非您指定VALUE属性,否则不会).因此,您需要相应地更改C代码:

#include <stdio.h>
#include <math.h>

float sin2(float *x) {
  return sin(*x) * sin(*x);
}

float integrate(float(*func)(float*),float* a,float* b,int* intsteps);

int main() {
  float integral;
  float a=0.;
  float b=1.;
  int intsteps=10000;


  integral = integrate(sin2,&a,&b,&intsteps);
  printf("%f",integral);
  return 0;
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读