f2pyを利用してPythonのライブラリを作成する

Pythonのライブラリであるnumpyをインストールすると、f2pyがインストールされる。これは何かというと、Fortranのコードをf2pyでコンパイルして.so形式のファイルを作成するもので、作成された.so形式のファイルはPythonのimport文で読み込むことができる。f2pyを利用すれば独自のライブラリを作成することができるわけである。ただし、Fortranを学ぶ必要があるので少し大変かもしれない。使用するFortranはGNU Fortranがあるので、あらかじめインストールしておくとよい。

作成環境

Linux Mint 20.3 MATE Edition
GNU Fortran 10.3.0
Visual Studio Code 1.67.0

拡張機能
Modern Fortran v3.0.2022042917
Fortran Intellisens v0.6.2

GNU Fortranのインストール

GNU Fortranは単体でインストールすることはなく、いくつかのパッケージをインストールする必要がある。GNU FortranがGCCを使用するためだ。

sudo apt install software-properties-common
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install build-essential
sudo apt install gdb
sudo apt install gfortran

Linux Mintでは、gdbが10.2、gccおよびg++は9.4.0がインストールされるはずである。最新版の12ではないが、11までならSynapticを利用してインストールすることが可能だ。ただし、インストールしただけでは利用することはできないので、update-alternatives –installコマンドで登録し、update-alternatibes –configで切り替えればよい。下記は、gfortran-10とgfortran-11をインストール後にupdate-alternatives –configを実行してみた例である。

$ update-alternatives --config gfortran            
alternative gfortran (/usr/bin/gfortran を提供) には 3 個の選択肢があります。

  選択肢    パス                優先度  状態
------------------------------------------------------------
  0            /usr/bin/gfortran-11   11        自動モード
* 1            /usr/bin/gfortran-10   10        手動モード
  2            /usr/bin/gfortran-11   11        手動モード
  3            /usr/bin/gfortran-9    9         手動モード

現在の選択 [*] を保持するには <Enter>、さもなければ選択肢の番号のキーを押してください: 

Linuxのディストリビューションによっては、gfortran以外、すでにインストールされていることもある。ちなみにUbuntu 22.04LTSでは、GCC-11がインストールされている。GCCやその他がインストールされているかどうか確認するには、以下のコマンドをそれぞれ使用する。

gcc --version
g++ --version
gdb --version
gfortran --version

GNU Fortranをインストールしたら、Visual Studio Codeを起動して拡張機能をインストールする。併せてC/C++という拡張機能もインストールされるので、関係ないからといって削除してはならない。

ライブラリを作成する

例として角度・ラジアンを相互変換するライブラリangle_demo.f90を作成してみた。

! Fortranのデモコード
! 引数は必ず以下のようにすること
! 入力変数はintent(in)
! 出力変数はintent(out)

! 時分秒を角度に換算する
subroutine hmstoangle(h, m, s, angle)
    implicit none

    double precision, intent(in) :: h, m, s
    double precision, intent(out) :: angle

    angle = 15.0d0 * (h + m / 60.0d0 + s / 3600.0d0)

    return
end subroutine hmstoangle

! 角度をラジアンに変換
subroutine radians(x, radian)
    implicit none

    double precision, parameter :: PI = 3.141592653589793d0
    double precision, parameter :: RAD = 180.0d0 / PI

    double precision, intent(in) :: x
    double precision, intent(out) :: radian

    radian = x / RAD

    return
end subroutine radians

! ラジアンを角度に変換
subroutine degrees(x, angle)
    implicit none

    double precision, parameter :: PI = 3.141592653589793d0
    double precision, parameter :: RAD = 180.0d0 / PI

    double precision, intent(in) :: x
    double precision, intent(out) :: angle

    angle = x * RAD

    return
end subroutine degrees

f2pyでコンパイル

f2py -m angle_demo -c angle_demo.f90

コンパイルすると、次のようなファイルが作成される。このまま使用しても問題はないが、ファイル名を短い名前に変更しておくとよい。

angle_demo.cpython-38-x86_64-linux-gnu.so → angle_demo.so

デモコード demo.py

実際に確認のために、以下のようなデモコードを書いてみた。呼び出しはライブラリ名.サブルーチン名(引数, …)である。

import angle_demo


h = 21.0
m = 4.0
s = 39.935

print('入力 %2dh %2dm %5.3fs => ' % (h, m, s), end='')
angle = angle_demo.hmstoangle(h, m, s)
print('%9.6f\n' % angle)

# 角度をラジアンに変換
rad = angle_demo.radians(angle)
print('ラジアン = %10.8f' % rad)

# ラジアンを角度に変換
angle = angle_demo.degrees(rad)
print('角度     = %9.6f' % angle)

実行結果

入力 21h  4m 39.935s => 316.166396

ラジアン = 5.51814459
角度     = 316.166396

コンパイルした.soとPythonコードは基本的に同じディレクトリに配置する。別のディレクトリに配置する場合は次のようにする。

libというディレクトリに配置してimport文で読み込む

from lib import angle_demo