4

C/C++へのコールバック関数ポインタとしてfortran 77関数を渡すことは可能ですか? もしそうなら、どのように?

Web で見つけた情報は Fortran 90 以降に関するものですが、私のレガシー コード ベースは 77 です。

どうもありがとう

4

1 に答える 1

6

FORTRAN 77 で実行できる場合は、コンパイラとプラットフォーム固有になります。Fortran 2003 の新しい ISO C バインディングは、Fortran と C、および C++ などの C の呼び出し規則に従う、または従うことができる任意の言語を混在させる標準的な方法を提供します。正式には Fortran 2003 の一部であり、Fortran 2003 全体を完全にサポートする Fortran コンパイラはほとんどありませんが、ISO C バインディングは、gfortran、g95、Sun、ifort などを含む多数の Fortran 95 コンパイラでサポートされています。特定のメソッドについて何らかのメソッドを考え出すよりも、これらの Fortran 95 コンパイラの 1 つと ISO C Binding メソッドを使用することをお勧めします。FORTRAN 77 は Fortran 95 のサブセットであるため、Fortran 95 を使用してこの新しい機能を追加し、レガシー コードをこれらのコンパイラのいずれかでコンパイルしてみませんか?

ISO C Binding を使用して C から Fortran プロシージャを呼び出しましたが、それらをポインターとして渡していません。それは可能であるべきです。手順は次のとおりです。

1) Bind(C) 属性を使用して Fortran 関数を宣言します。

2) C の型と一致する integer(c_int) などの特殊な型を使用して、すべての引数を宣言します。

ステップ 1 と 2 により、Fortran 関数が C と相互運用可能になります。

3) Fortran 組み込み関数 "c_funloc" を使用して、この Fortran 関数への C ポインターを取得し、ポインター値を "c_funptr" 型のポインターに割り当てます。

4) Fortran コードでは、インターフェイスを使用して関数ポインターを渡す C ルーチンを宣言し、Fortran 用語で宣言しますが、Fortran コンパイラーが認識できるように、Bind(C) 属性と相互運用可能な型を使用します。 C 呼び出し規則を使用して、C ルーチンを Fortran と相互運用可能にします。

その後、Fortran コードで C ルーチンを呼び出すときに、ステップ 3 で作成した関数ポインターを渡すことができます。

更新: コード例: Fortran メイン プログラム「test_func_pointer」は、Fortran 関数「my_poly」へのポインターを C ルーチン「C_Func_using_Func_ptr」に渡し、その C 関数から結果を受け取ります。

module func_pointer_mod

   use, intrinsic :: iso_c_binding

   implicit none

   interface C_func_interface

      function C_Func_using_Func_ptr ( x, Func_ptr ) bind (C, name="C_Func_using_Func_ptr")

         import

         real (c_float) :: C_Func_using_Func_ptr
         real (c_float), VALUE, intent (in) :: x
         type (c_funptr), VALUE, intent (in) :: Func_ptr

      end function C_Func_using_Func_ptr

   end interface C_func_interface


contains

   function my_poly (x) bind (C, name="my_poly")

      real (c_float) :: my_poly
      real (c_float), VALUE, intent (in) :: x

      my_poly = 2.0 * x**2 + 3.0 * x + 5.0

      return

   end function my_poly

end module func_pointer_mod


program test_func_pointer

   use, intrinsic :: iso_c_binding

   use func_pointer_mod

   implicit none

   type (c_funptr) :: C_func_ptr

   C_func_ptr = c_funloc ( my_poly )

   write (*, *) C_Func_using_Func_ptr ( 2.5_c_float, C_func_ptr )

   stop

end program test_func_pointer

float C_Func_using_Func_ptr (

   float x,
   float (*Func_ptr) (float y)

) {

   return ( (*Func_ptr) (x) );

}
于 2010-05-25T05:38:05.290 に答える