在C中使用Fortran代码 [英] Use Fortran-code in C

查看:154
本文介绍了在C中使用Fortran代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在C中使用Fortran例程,但我不工作。我不知道我犯了什么错误。这里我的Fortran代码包括我想在C中使用的Integration-Module:

 模块集成
隐式none

包含

函数Integrate(func,a,b,intsteps)结果(整数)

接口
实函数func x)
real,intent(in):: x
结束函数func
结束接口

real ::整数,a,b
整数: :intsteps
intent(in):: a,b,intsteps
optional :: intsteps

real :: x,dx
integer :: i,n $如果(存在(intsteps))n = intsteps

dx =(ba )/ n

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

整数=整数* dx
结束函数

结束模块整合


real(c_float)函数n wrapper_integrate(func,a,b,intsteps)结果(整数)bind(C,name ='integrate')
使用iso_c_binding
使用整合

界面
真正的(c_float)函数func(x)绑定(C)
内部:: iso_c_binding
真实(c_float),intent(in):: x
结束函数func
(c_float):: a,b
整数(c_int),intent(in):: intsteps
可选:: intsteps
if(present (func,a,b)
endif
$ b $积分=积分(func,a,b,intsteps)
else
积分= b $ b结束函数wrapper_integrate

和我的C代码:

  #include  
#include< math.h>

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


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

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

如果我执行

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

我得到

  (*)(float),float,float,int)'

有谁知道如何处理?

解决方案

如果您使用模块 ISO_C_Binding 将函数从C传递给Fortran作为函数指针 C_FUNPTR
请参阅此处细节。



您的情况如下:

  real c_float)函数wrapper_integrate(func,a,b,intsteps)result(整型)bind(C,name ='integrate')
use iso_c_binding
使用整合

抽象接口
函数iFunc(x)bind(C)
use,intrinsic :: iso_c_binding
real(c_float):: iFunc
real(c_float),intent(in):: x
结束函数iFunc
结束接口

类型(C_FUNPTR),INTENT(IN),VALUE :: func
real(c_float):: a,b
整数(c_int),intent(in):: intsteps
可选:: intsteps

过程(iFunc),指针:: myfunc
调用c_f_procpointer(func,myfunc)

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

结束函数wrapper_integrate

显然,您的解决方案是更优雅; - )另外,请注意,Fortran通过引用传递变量(除非您指定了 VALUE 属性,您不会T)。因此,您需要相应地更改您的C代码:

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

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


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

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


积分=积分(sin2,& a,& b,& intsteps);
printf(%f,integral);
返回0;
}


I try to use a fortran-routine in C, but I doesn't work. I don't know where I made a mistake. Here my Fortran-code including the Integration-Module, which I want to use in C:

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, 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
    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,a,b,intsteps)
  else
    integral = Integrate(func,a,b)
  endif

end function wrapper_integrate

and my C-Code:

#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;
}

if I execute

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

I get

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

Does anyone know how to handle this?

解决方案

If you are using the module ISO_C_Binding, you can directly passing a function from C to Fortran as a function pointer C_FUNPTR. See here for details.

In your case, this would look like:

real(c_float) function wrapper_integrate(func, a, b, intsteps) result(integral) bind(C, 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,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)
  else
    integral = Integrate(myfunc,a,b)
  endif

end function wrapper_integrate

Obviously, your solution is more elegant ;-)

Also, please note that Fortran passes variables by reference (unless you specify the VALUE attribute, which you don't). Therefore, you need to change you C code accordingly:

#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;
}

这篇关于在C中使用Fortran代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆