導入: なぜBIND(C)が重要なのか
数値計算の現場では、計算速度が求められるコア部分をFortranで記述し、フロントエンドやインターフェース部分をPythonやC++で構築する構成が一般的です。しかし、Fortranと他の言語を直接つなごうとすると、Fortran特有の「名前修飾(名前の最後にアンダースコアが付くなど)」という壁にぶつかります。この問題を解決し、他言語からFortranのルーチンを確実に呼び出すために必須となるのがBIND(C)属性です。
基礎知識: BIND(C)とは何か
通常、Fortranで定義した手続きは、コンパイラによって内部的に名前が変換されます。例えば「calc_data」という名前の手続きが、コンパイル後に「calc_data_」のように変更される現象です。これでは、C言語側から正しい名前で呼び出すことができません。BIND(C)を使用することで、コンパイラに対して「C言語の命名規則に従い、名前の変更を禁止する」という指示を出し、言語間での相互運用性を保証します。
実装/解決策: 名前を明示的に指定する
BIND(C)は、手続きの定義時に属性として付与します。特にname=引数を指定することで、Fortran側の内部名と、外部から見える名前を分離できます。これにより、Fortran側のソースコードでは分かりやすい名前を使いつつ、外部インターフェース用には標準化された名前を割り当てることが可能になります。
サンプルプログラム: BIND(C)の適用例
以下のコードは、Fortran側で手続きを定義し、それを外部から「c_compute_val」という名前で呼び出せるように設定する例です。
! Fortran側のソースコード
module math_module
use iso_c_binding, only: c_int
implicit none
contains
! BIND(C)を使用し、外部から見える名前を "c_compute_val" に固定
subroutine compute_val(x) bind(c, name="c_compute_val")
integer(c_int), intent(in) :: x
! 渡された値を2倍するだけの単純な計算
print , "計算結果: ", x 2
end subroutine compute_val
end module math_module
応用・注意点: 現場で役立つポイント
1. 大文字と小文字の区別: C言語は名前を厳密に区別します。name引数で指定する文字列は、呼び出し側が期待する文字列と完全に一致(通常はすべて小文字)させる必要があります。
2. データ型の互換性: BIND(C)を使う際は、必ず iso_c_binding モジュールを利用してください。Fortranの `integer` 型とCの `int` 型はメモリ配置が異なる場合があるため、`c_int` や `c_double` といった型指定が不可欠です。
3. Pythonとの連携: Pythonの `ctypes` を使えば、上記のように作成した共有ライブラリを簡単に読み込めます。この際、BIND(C)で名前を固定しておけば、将来的にFortran側の実装を修正しても、Python側の呼び出しコードを変更せずに済むという大きなメリットがあります。
多言語混在環境を構築する際は、まず「名前の衝突」や「リンクエラー」を未然に防ぐために、このBIND(C)を徹底することをお勧めします。

コメント