cffi にて python を Fortran から 呼び出す
以下の記事を参考に、WSL で Fotrran から Python を呼び出してみます。 記事中の呼び出し方法3、CFFI を用いる方法です。比較的簡潔なのが特徴です。
Fortran と Python 間での配列のやり取りも簡単なようです。
Python 側のドキュメント
参考記事:
Write the name of the source file first:
実行例
記事中のままでは動かなかったのですが、dynamic lib の拡張子を OS に合わせて変える他に、WSL(Linux) の場合 gfortran でのコンパイル時に、ソースファイルを先頭に持ってくる必要があるようです。Dynamic Library の path の指定も必要でした。
下の例で $ export LD_LIBRARY_PATH が抜けていました。
(cffi) dyna@dyna:~/py$ python builder.py generating ./my_plugin.c (already up-to-date) the current directory is '/home/dyna/py' (cffi) dyna@dyna:~/py$ gfortran test.f90 -L. -lplugin -o test (cffi) dyna@dyna:~/py$ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/dyna/py (cffi) dyna@dyna:~/py$ ./test libGL error: MESA-LOADER: failed to open swrast: /usr/lib/dri/swrast_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib/x86_64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/lib/dri, suffix _dri) libGL error: failed to load driver: swrast Plot! (cffi) dyna@dyna:~/py$
なんかエラーが出てますが、デバイス・ドライバがらみで Python ではよくあることなので気にしませんw
import cffi ffibuilder = cffi.FFI() header = """ extern void pyplot(void); """ module = """ from my_plugin import ffi import numpy as np import matplotlib.pyplot as plt @ffi.def_extern() def pyplot(): xp = np.arange(-np.pi, np.pi, 0.1) yp = np.sin(xp) plt.plot(xp, yp) plt.show() print("Plot!") """ with open("plugin.h", "w") as f: f.write(header) ffibuilder.embedding_api(header) ffibuilder.set_source("my_plugin", r''' #include "plugin.h" ''') ffibuilder.embedding_init_code(module) ffibuilder.compile(target="libplugin.so", verbose=True) #ffibuilder.compile(target="plugin-1.5.*", verbose=True)
! test.f90 program call_python use, intrinsic :: iso_c_binding implicit none interface subroutine pytest() bind (c, name = 'pyplot') end subroutine pytest end interface call pytest() end program call_python