从C调用一个FORTRAN子程序

我正试图从C调用一个FORTRAN函数

我的问题是:

  1. 如果fortRoutine是我的fortran子程序的名字,那么我从C调用它作为fortRoutine_ 。 如果fortRoutine只包含一个字符数组参数,那么我可以像这样传递:

     fortRoutine_("I am in fortran"); 
  2. 在调用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编译器,但一般来说:

  1. 不,您需要为您的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. 
  2. 几乎总是通过引用传递,但是可以使用FORTRAN端伪参数上的属性来切换此行为。

     int value = 10; fortranFunc_(&value); // INTEGER I 

这里有一些参考,这些参考适用于各种编译器:

  • FORTRAN / C互操作性
  • gfortran – 与C的互操作性
  • 英特尔Fortran – 与C的互操作性
  • ISO_C_BINDING模块

答案取决于编译器和系统(技术上说,它的ABI)。 对于GCC(C,C ++,Ada和Fortran编译器),阅读Fortran 混合编程章节。