从 C 调用 FORTRAN 子例程

发布于 2024-12-17 05:05:27 字数 371 浏览 8 评论 0原文

我正在尝试从 C 调用 FORTRAN 函数

我的问题是:

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

    fortRoutine_("我使用的是 fortran");
    
  2. 当调用 FORTRAN 子例程时,何时应该使用按值传递以及何时按引用传递?

由于我是C语言新手,所以我对此一无所知。如果可能的话,请推荐一些好的教程链接。

I am trying to call a FORTRAN function from C

My questions are:

  1. If fortRoutine is the name of my fortran subroutine, then I am calling this from C
    as fortRoutine_. If fortRoutine contains only one character array argument, then can I pass like this:

    fortRoutine_("I am in fortran");
    
  2. While calling FORTRAN subroutines, when should I use pass by value and when pass by reference?

As I am new to C, I do not have a clue about this. If possible, please suggest some good tutorial links as well.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你曾走过我的故事 2024-12-24 05:05:28

现在执行此操作的方法是在 Fortran 端使用 Fortran ISO C 绑定。这是 Fortran 2003 语言标准的一部分,可在许多编译器中使用;它不是特定于 gcc 的。本网站的许多答案中都对此进行了描述。作为语言标准的一部分,它独立于编译器和平台。并且您不需要了解编译器的内部传递约定。 ISO C 绑定在 Fortran 子例程或函数的声明中使用时,会导致 Fortran 编译器使用 C 调用约定,以便可以直接从 C 调用该过程。您不需要添加隐藏参数或名称修改Fortran 子程序名称,即没有下划线。链接器使用的名称来自“bind”选项。

字符串是一个困难的情况,因为从技术上讲,在 C 中它们是字符数组,并且您必须在 Fortran 中匹配它。您还必须处理字符串的不同定义:C 以 null 结尾,Fortran 固定长度并用空格填充。该示例展示了这是如何工作的。数字更容易。数组的唯一问题是 C 是行优先而 Fortran 是列优先,因此多维数组会被转置。

int main ( void ) {

   char test [10] = "abcd";

   myfortsub (test);

   return 0;

}

将 C 编译为目标文件,然后

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

使用 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

The way to do this now is to use the Fortran ISO C Binding on the Fortran side. This is part of the Fortran 2003 language standard and is available in many compilers; it is not specific to gcc. It has been described in many answers on this site. As part of the language standard, it is compiler and platform independent. And you do not need to know about the internal passing conventions of the compiler. The ISO C Binding, when used in the declaration of a Fortran subroutine or function, causes the Fortran compiler to use the C calling conventions so that that procedure can be directly called from C. You do not need to add hidden arguments or name mangle the Fortran subroutine name, i.e., no underscores. The name used by the linker comes from the "bind" option.

Strings are a difficult case because technically in C they are arrays of characters and you have to match this in the Fortran. You also have to deal with the different definitions of strings: C is null terminated, Fortran fixed length and padded with blanks. The example shows how this works. Numbers are easier. The only issue with arrays is that C is row-major and Fortran column-major so that multi-dimensional arrays are transposed.

int main ( void ) {

   char test [10] = "abcd";

   myfortsub (test);

   return 0;

}

and

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

You compile the C to an object file and use gfortran to compile the fortran and link both:

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

gfortran-mp-4.6   \
     test_fortsub.o  \
     myfortsub.f90  \
     -o test_fortsub.exe

Output is:

 >abcd<           4
苍暮颜 2024-12-24 05:05:28

当然,这一切都取决于您的 FORTRAN 编译器,但一般来说:

  1. 不,您需要为字符串传递一个隐藏的长度参数。一些编译器将这些参数与其他参数直接交错放置在字符串之后。其他人,将所有字符串长度参数分组到参数列表的末尾。

    char str[11] = {0};
    fortranFunc_(str, sizeof(str) - 1);
    // 请记住 'str' 需要以 null 结尾
    // 并将用空格填充以适应长度
    // 所以对于 C 将字符串传递给 Fortran 指定长度
    // 减去 1,这样您就可以在所有字符串上添加 nul 终止符
    // 由 FORTRAN 填充,修剪掉所有空格。
    
  2. 几乎总是通过引用传递,但您可以使用 FORTRAN 端虚拟参数上的属性来切换此行为。

    int 值 = 10;
    fortranFunc_(&值);
    // 整数我
    

以下是一些参考资料,适用于各种编译器:

Of course this all depends on your FORTRAN Compiler, but generally speaking:

  1. No, you'll need to pass a hidden length argument for your string. Some compilers interleave these with the other parameters, directly after the string. Others, group all string length arguments at the end of the argument list.

    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. Almost always it is pass by reference, but you can toggle this behavior using attributes on the dummy arguments on the FORTRAN side.

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

Here are some references, which are applicable based on various compilers:

请你别敷衍 2024-12-24 05:05:28

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

The answer depends upon the compiler and the system (technically, its ABI). For GCC (which is a C, a C++, an Ada, and a Fortran compiler) read the fortran mixed programming chapter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文