16

CからFORTRAN関数を呼び出そうとしています

私の質問は次のとおりです。

  1. fortRoutineが私のFortranサブルーチンの名前である場合、これをCから。として呼び出していfortRoutine_ます。fortRoutine文字配列引数が1つしかない場合は、次のように渡すことができますか?

    fortRoutine_("I am in fortran");
    
  2. FORTRANサブルーチンを呼び出すときに、値渡しと参照渡しをいつ使用する必要がありますか?

私はCに慣れていないので、これについての手がかりはありません。可能であれば、いくつかの良いチュートリアルリンクも提案してください。

4

3 に答える 3

28

これを行う方法は、Fortran側でFortranISOCバインディングを使用することです。これはFortran2003言語標準の一部であり、多くのコンパイラーで使用できます。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;

}

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
于 2011-11-21T08:15:27.657 に答える
4

もちろん、これはすべて FORTRAN コンパイラに依存しますが、一般的に言えば:

  1. いいえ、文字列の隠し長さ引数を渡す必要があります。一部のコンパイラは、文字列の直後にこれらを他のパラメーターとインターリーブします。その他、すべての文字列長の引数を引数リストの最後にグループ化します。

    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
    

さまざまなコンパイラに基づいて適用できる参考文献を次に示します。

于 2011-11-21T06:34:24.443 に答える
1

答えは、コンパイラとシステム (技術的には、その ABI) によって異なります。GCC (C、C++、Ada、および Fortran コンパイラ) については、fortran 混合プログラミングの章をお読みください。

于 2011-11-21T06:23:17.883 に答える