从C调用FORTRAN子例程

Kit*_*ttu 13 c fortran fortran-iso-c-binding

我试图从C调用FORTRAN函数

我的问题是:

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

    fortRoutine_("I am in fortran");
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在调用FORTRAN子例程时,何时应该使用pass by值和何时通过引用传递?

由于我是C的新手,我对此并不了解.如果可能的话,请提供一些很好的教程链接.

M. *_* B. 23

现在这样做的方法是在Fortran端使用Fortran ISO C绑定.这是Fortran 2003语言标准的一部分,可在许多编译器中使用; 它不是特定于gcc.本网站上的许多答案都有描述.作为语言标准的一部分,它与编译器和平台无关.而且您不需要了解编译器的内部传递约定.当在Fortran子例程或函数的声明中使用时,ISO C绑定会导致Fortran编译器使用C调用约定,以便可以直接从C调用该过程.您不需要添加隐藏的参数或名称Fortran子例程名称,即没有下划线.链接器使用的名称来自"绑定"选项.

字符串是一个困难的案例,因为从技术上来说,它们是字符数组,你必须在Fortran中匹配它.您还必须处理字符串的不同定义:C为空终止,Fortran固定长度并填充空格.该示例显示了这是如何工作的.数字更容易.数组的唯一问题是C是row-major和Fortran column-major,因此多维数组被转置.

int main ( void ) {

   char test [10] = "abcd";

   myfortsub (test);

   return 0;

}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

您将C编译为目标文件并使用gfortran编译fortran并链接两者:

gcc-mp-4.6   \
         -c  \
         test_fortsub.c

gfortran-mp-4.6   \
     test_fortsub.o  \
     myfortsub.f90  \
     -o test_fortsub.exe
Run Code Online (Sandbox Code Playgroud)

输出是:

 >abcd<           4
Run Code Online (Sandbox Code Playgroud)

  • 一般来说这是破产方式,但我认为,很多时候,如果C程序员说,他们通常真的不想挖掘他们的遗留FORTRAN 77和旧代码.有时候用C语言写一个包装器会更好. (2认同)

Bas*_*tch 1

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