从C包装器调用FORTRAN函数
我是这方面的新手,但我需要从C访问一些旧的Fortran 77函数。 如果可能的话,我不想修改Fortran代码,我更愿意编写一个包装器来从C调用Fortran函数。我希望得到一个最小的工作示例(在Linux上)。我所做的: 在文件somefunction.f中:从C包装器调用FORTRAN函数,c,fortran,fortran77,C,Fortran,Fortran77,我是这方面的新手,但我需要从C访问一些旧的Fortran 77函数。 如果可能的话,我不想修改Fortran代码,我更愿意编写一个包装器来从C调用Fortran函数。我希望得到一个最小的工作示例(在Linux上)。我所做的: 在文件somefunction.f中: REAL*8 FUNCTION MYFUNC(ZZ) IMPLICIT NONE REAL*8 ZZ, T1 T1 = ZZ + 1.0D0 MYFUNC = T1 RETU
REAL*8 FUNCTION MYFUNC(ZZ)
IMPLICIT NONE
REAL*8 ZZ, T1
T1 = ZZ + 1.0D0
MYFUNC = T1
RETURN
END
使用gfortran-csomefunction.f-osomefunction.o
编译
在文件debug.c中:
#include <stdio.h>
double cfunc(double x) {
double result = myfunc_( &x );
return result;
}
int main() {
double test = cfunc(3.0);
printf(" %.15f ",test);
}
#包括
双cfunc(双x){
双重结果=myfunc_x(&x);
返回结果;
}
int main(){
双重测试=cfunc(3.0);
printf(“%.15f”,测试);
}
使用gcc-cdebug.c-odebug.o
编译
然后我给出了gcc debug.o somefunction.o
和/a.out
然而,我得到的不是3+1=4,而是无意义的数字。我如何纠正这个问题
附言:如果这个问题解决了,我的实际功能会更复杂一些:
COMPLEX*16函数MYFUNC(ZZ)
,并且ZZ也是一个复合体,我应该做什么更改好的,仅供参考,正如@IanBush所说,C程序应该声明myfunc的返回类型
#include <stdio.h>
double myfunc_(double*);
double cfunc(double x) {
double result = myfunc_( &x );
return result;
}
int main() {
double test = cfunc(3.0);
printf(" %.15f ",test);
}
#包括
双myfunc_u2;(双*);
双cfunc(双x){
双重结果=myfunc_x(&x);
返回结果;
}
int main(){
双重测试=cfunc(3.0);
printf(“%.15f”,测试);
}
除了返回类型之外,您还需要注意Fortran过程名称被破坏成从C访问的符号的方式。没有标准,它完全取决于Fortran编译器和平台,因此如果您想要可移植性,您必须使用一些配置时间检测和宏
例如,需要从C调用FortranMYFUNC()
,如下所示:
- Windows上英特尔Fortran下的MYFUNC()
- IBM XL Fortran(
下的xlf
)myfunc()
- 在大多数其他情况下(包括Windows上的GNU Fortran),myfunc_u3;()
\u MOD\u
,\u mp\u
等会在名称前面加上损坏的前缀。)
现代的Fortran解决方案是在Fortran端声明一个
bind(C)
例程,这将关闭这种混乱(或者您可以指定一个显式的绑定名称)。您是否在C中的任何位置声明myfunc的返回类型?您是对的,这就是问题所在。谢谢对于其他要点的任何提示,我们也将不胜感激@克雷格斯特伊:不,不是。Real*8不是也从来不是标准Fortran的一部分,因此它的行为是由实现定义的,并且有一些编译器不支持Real*8。相反,应该使用标准定义的种类机制。另请看回答这个问题的最佳方法是Fortran的标准定义方式与C的接口。@IanBush我没有说这是一个标准,只是它已经存在了几十年。fortran是一种后缘语言。编写新代码的唯一原因是与传统的科学库接口[这些库可能有数百万行使用real*8
]的代码]。real*8
的使用比kind
早至少二十年。因此,每一个需要相关的可靠fortran编译器都将支持real*8
。而且,real*8xs
比real(KIND=8)::xs更为紧凑,因此它因其所需/使用的东西简洁而获胜。而且,F2008允许使用更好的REAL64
。您已经使用fortran 77进行了标记,但是如果可以选择在fortran端编写包装器,我强烈建议使用fortran 2003提供的iso_c_binding
模块:a)它定义了保证与其c对应项匹配的数据类型(=无需猜测real*8
是否真的是double
,等等),以及b)abind(c,name=“foo”)
函数在c中有明确定义的签名和符号名称(foo(…)
保证按预期工作)。简言之,它将带您走出泥泞的实现定义行为区域,进入符合标准的C/fortran的定义良好的领域。