在 C 中使用 Fortran 代码
Use Fortran-code in C
我尝试在 C 中使用 fortran 例程,但我没有用。我不知道我在哪里犯了错误。这是我的 Fortran 代码,包括我想在 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
和我的 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, float, int)'
有人知道怎么处理吗?
如果您正在使用模块 ISO_C_Binding
,您可以直接将函数作为函数指针从 C 传递到 Fortran C_FUNPTR
。
有关详细信息,请参阅 here。
在你的例子中,这看起来像:
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
显然,您的解决方案更优雅 ;-)
此外,请注意 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;
}
您使用的是 C++ 编译器,而不是 C 编译器。链接约定可能不同。
而且你忘了 link 数学库(因为 sin)
gcc -c main.c
gfortran -c integration.f95
gcc main.o integration.o -lm
OP 使用了 gnu c++ 编译器。这是一个解决方案,使用来自几个响应者的信息,对我来说,使用 c++ 编译器——而不是 c 编译器——是有效的:
文件'integration.f95':
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
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
文件'main.c':
#include <stdio.h>
#define _USE_MATH_DEFINES
#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() {
int intsteps=10000;
float integral;
float a=0.;
float b=3.1416;
integral = integrate(sin2, &a, &b, &intsteps);
printf("The numerical value of \int_0^\pi dx sin^2x = %f\n",integral);
printf("The exact value of \int_0^\pi dx sin^2x = %f\n",M_PI_2);
return 0;
}
文件'compile.txt':
gcc -c main.c
gfortran -c integration.f95
g++ -o intsinq main.o integration.o
我尝试在 C 中使用 fortran 例程,但我没有用。我不知道我在哪里犯了错误。这是我的 Fortran 代码,包括我想在 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
和我的 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, float, int)'
有人知道怎么处理吗?
如果您正在使用模块 ISO_C_Binding
,您可以直接将函数作为函数指针从 C 传递到 Fortran C_FUNPTR
。
有关详细信息,请参阅 here。
在你的例子中,这看起来像:
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
显然,您的解决方案更优雅 ;-)
此外,请注意 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;
}
您使用的是 C++ 编译器,而不是 C 编译器。链接约定可能不同。
而且你忘了 link 数学库(因为 sin)
gcc -c main.c
gfortran -c integration.f95
gcc main.o integration.o -lm
OP 使用了 gnu c++ 编译器。这是一个解决方案,使用来自几个响应者的信息,对我来说,使用 c++ 编译器——而不是 c 编译器——是有效的:
文件'integration.f95':
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
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
文件'main.c':
#include <stdio.h>
#define _USE_MATH_DEFINES
#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() {
int intsteps=10000;
float integral;
float a=0.;
float b=3.1416;
integral = integrate(sin2, &a, &b, &intsteps);
printf("The numerical value of \int_0^\pi dx sin^2x = %f\n",integral);
printf("The exact value of \int_0^\pi dx sin^2x = %f\n",M_PI_2);
return 0;
}
文件'compile.txt':
gcc -c main.c
gfortran -c integration.f95
g++ -o intsinq main.o integration.o