从C调用一个FORTRAN子程序
我正试图从C调用一个FORTRAN函数
我的问题是:
-
如果
fortRoutine
是我的fortran子程序的名字,那么我从C调用它作为fortRoutine_
。 如果fortRoutine
只包含一个字符数组参数,那么我可以像这样传递:fortRoutine_("I am in fortran");
-
在调用FORTRAN子程序的时候,我应该何时使用按值传递,何时传递参考?
因为我是C新手,所以我对此没有任何线索。 如果可能的话,请build议一些很好的教程链接。
现在要做到这一点的方法是在Fortran一侧使用Fortran ISO C Binding。 这是Fortran 2003语言标准的一部分,可用于许多编译器; 它不是特定于gcc。 在这个网站的许多答案中都有描述。 作为语言标准的一部分,它是独立于编译器和平台的。 而且你不需要知道编译器的内部传递约定。 当用于声明Fortran子例程或函数时,ISO C Binding使Fortran编译器使用C调用约定,以便可以直接从C中调用该过程。不需要添加隐藏参数或命名为Fortran子程序名称,即没有下划线。 链接器使用的名称来自“绑定”选项。
string是一个困难的情况,因为从技术上讲,它们是字符数组,你必须在Fortran中匹配。 您还必须处理string的不同定义:C为空终止,Fortran固定长度并填充空格。 这个例子显示了这个如何工作。 数字更容易。 数组唯一的问题是,C是行主要和Fortran列主要,以便multidimensional array转换。
int main ( void ) { char test [10] = "abcd"; myfortsub (test); return 0; }
和
subroutine myfortsub ( input_string ) bind ( C, name="myfortsub" ) use iso_c_binding, only: C_CHAR, c_null_char implicit none character (kind=c_char, len=1), dimension (10), intent (in) :: input_string character (len=10) :: regular_string integer :: i regular_string = " " loop_string: do i=1, 10 if ( input_string (i) == c_null_char ) then exit loop_string else regular_string (i:i) = input_string (i) end if end do loop_string write (*, *) ">", trim (regular_string), "<", len_trim (regular_string) return end subroutine myfortsub
你把C编译成一个目标文件,然后用gfortran编译fortran并链接两者:
gcc-mp-4.6 \ -c \ test_fortsub.c gfortran-mp-4.6 \ test_fortsub.o \ myfortsub.f90 \ -o test_fortsub.exe
输出是:
>abcd< 4
当然,这一切都取决于你的FORTRAN编译器,但一般来说:
-
不,您需要为您的string传递一个隐藏的长度参数。 一些编译器将这些与其他参数交错,直接在string之后。 其他人,在参数列表的末尾分组所有string长度参数。
char str[11] = {0}; fortranFunc_(str, sizeof(str) - 1); // remember that 'str' will need to be null terminated // and will be padding with spaces to fit the length // so for C passing strings to Fortran specify the length // less 1 so you can add a nul terminator, and on all strings // being filled in by FORTRAN, trim-end all spaces.
-
几乎总是通过引用传递,但是可以使用FORTRAN端伪参数上的属性来切换此行为。
int value = 10; fortranFunc_(&value); // INTEGER I
这里有一些参考,这些参考适用于各种编译器:
- FORTRAN / C互操作性
- gfortran – 与C的互操作性
- 英特尔Fortran – 与C的互操作性
- ISO_C_BINDING模块
答案取决于编译器和系统(技术上说,它的ABI)。 对于GCC(C,C ++,Ada和Fortran编译器),阅读Fortran 混合编程章节。