Fortran Builder は、実行形式(.exe)以外にも、ダイナミックリンクライブラリ(.dll)やスタティックライブラリ(.a)の作成が行えます。特に DLL は、様々な環境から使える強力な仕組みであるため、Fortran で書いた計算ルーチンを Excel や Python などの他の環境から使うことが可能です。
ここでは、Fortran Builder を用いて DLL ファイルを作成し、Python から呼び出す例を示します。
この例では、
- Fortran 側で C との相互利用可能性 を用いる。
- Python 側で ctypes モジュールを用いる。
これにより、C のインターフェースを介して、Python から Fortran 手続を呼び出しています。
(追記)
C からの呼び出し例
ラッパー例1
ラッパー例2
その他のプログラム例
① DLL プロジェクトを作成する
メニューから「ファイル > 新規作成 > プロジェクト」を選択してください。
以下のような画面が表示されますので、「ダイナミックリンクライブラリ」を選択後に「プロジェクトの名前」を myflib として「次へ」ボタンを押してください。
以下のような画面が表示されますが、このまま「OK」ボタンを押して次に進んでください。
以下のような画面が表示されれば、DLL プロジェクトの作成は無事行われています。
次のステップに進んでください。
② プロジェクトにソースファイルを追加する
メニューから「ファイル > 新規作成 > ファイル」を選択してください。
以下のような画面が表示されますので、「Fortran 自由形式ソースファイル」を選択後に「OK」ボタンを押してください。
以下のような画面が表示されますので、「ファイル名」を myprog として「OK」ボタンを押してください。
以下のような画面が表示されれば、ソースファイルの作成は無事行われています。
次のステップに進んでください。
③ ソースファイルにプログラムを書く
以下のソースプログラムを入力してください。
倍精度実数 a と b を引数にとり、a + b を倍精度実数として返す関数です。
特に、Fortran 2003 から導入された C との相互利用可能性 を用いて書かれていることに注意してください。
(これにより、インターフェース的には、外部から C 関数として呼び出すことができます。)
function myfunc(a, b) bind(c, name = "myfunc") use iso_c_binding real(c_double), value, intent(in) :: a, b real(c_double) myfunc myfunc = a + b end function
入力が終わったら、メニューから「ファイル > 上書き保存」(または Ctrl + S)を選択してください。
④ プロジェクトをビルドする(DLL ファイルを生成する)
メニューから「プロジェクト > プロジェクトの設定」を開いてください。
(これにより、プログラムの実行に必要な nAG Fortran Compiler のランタイムライブラリが、生成される DLL に結合されます。)
メニューから「プロジェクト > ビルド」を選択してください。
問題が無ければ、メッセージウィンドウに以下のように表示され、プロジェクトフォルダーに DLL ファイルが作成されます。
※ プロジェクトフォルダーを開く
メニュー「表示 > プロジェクトフォルダー」から、プロジェクトフォルダーを直接開くことができます。
フォルダーの中に、DLL ファイル(myflib.dll)が作成されていることが分かります。
⑤ DLL を Python から呼び出す
以下に Python のコード例を示しますが、DLL ファイルのパスはユーザー環境に合わせて適宜書き換えてください。
特に、Python の ctypes モジュール(C と互換性のあるデータ型を提供し、DLL/共有ライブラリ内の C 関数を呼び出すためのモジュール)を利用していることに注意してください。
from ctypes import * myflib = WinDLL("myflib.dll") myflib.myfunc.restype = c_double myflib.myfunc.argtypes = [c_double, c_double] a = 2.0 b = 3.0 print(myflib.myfunc(a, b))
実行結果:
5.0
(追記)C からの呼び出し例
C から呼び出す場合は以下の様になります。
#include <stdio.h> extern double myfunc(double a, double b); int main(int argc, char *argv[]) { double a, b; a = 2.0; b = 3.0; printf("%f\n", myfunc(a, b)); return 0; }
(追記)ラッパー例1
既存の外部手続(サブルーチン・関数)に手を加えたくない場合は、例えば以下の様に、ラッパーを書くという方法もあります。
function myfunc(a, b)
double precision, intent(in) :: a, b
double precision myfunc
myfunc = a + b
end function
function myfunc_wrap(a, b) bind(c, name = "c_myfunc")
use iso_c_binding
interface
function myfunc(x, y)
double precision, intent(in) :: x, y
double precision myfunc
end function
end interface
real(c_double), value, intent(in) :: a, b
real(c_double) myfunc_wrap
myfunc_wrap = myfunc(a, b)
end function
この場合、Python からの呼び出しは以下の様になります。
from ctypes import * myflib = WinDLL("myflib.dll") myflib.c_myfunc.restype = c_double myflib.c_myfunc.argtypes = [c_double, c_double] a = 2.0 b = 3.0 print(myflib.c_myfunc(a, b))
(追記)ラッパー例2
既存のモジュール手続(サブルーチン・関数)に手を加えたくない場合は、例えば以下の様に、ラッパーを書くという方法もあります。
module mymod
implicit none
contains
function myfunc(a, b)
double precision, intent(in) :: a, b
double precision myfunc
myfunc = a + b
end function
end module
function mymod_myfunc_wrap(a, b) bind(c, name = "c_mymod_myfunc")
use mymod
use iso_c_binding
real(c_double), value, intent(in) :: a, b
real(c_double) mymod_myfunc_wrap
mymod_myfunc_wrap = myfunc(a, b)
end function
この場合、Python からの呼び出しは以下の様になります。
from ctypes import * myflib = WinDLL("myflib.dll") myflib.c_mymod_myfunc.restype = c_double myflib.c_mymod_myfunc.argtypes = [c_double, c_double] a = 2.0 b = 3.0 print(myflib.c_mymod_myfunc(a, b))
(追記)その他のプログラム例
より複雑なプログラム例は「Python から Fortran を呼び出す例」をご参照ください。