this page(特にCからFortranの共通ブロックにアクセスする方法)とQ/A pageではPythonからC structにアクセスする方法については、次のように共通ブロックにアクセスできるようです。以下):
mylib.f90
subroutine fortsub()
implicit none
integer n
common /mycom/ n
print *, "fortsub> current /mycom/ n = ", n
end
コンパイル:
$ gfortran -shared -fPIC -o mylib.so mylib.f90
test.py
from __future__ import print_function
import ctypes
class Mycom(ctypes.Structure):
_fields_ = [ ("n", ctypes.c_int) ]
mylib = ctypes.CDLL("./mylib.so")
mycom = Mycom.in_dll(mylib, "mycom_")
print(" python> modifying /mycom/ n to 777")
mycom.n = 777
fortsub = mylib.fortsub_
fortsub()
テスト:
ここ
$ python test.py
python> modifying /mycom/ n to 777
fortsub> current /mycom/ n = 777
、(仮定のgfortranで)共通ブロック(ここでは、mycom
)の名前が小文字に行われ、1アンダースコアが添付ことに注意してください。この規約はコンパイラに依存しているため、共通ブロック(特にiso_c_binding
の助けを借りて)で値を設定/取得するための新しいFortranルーチンを作成し、Pythonからこれらのルーチンを呼び出す方がより強固で移植性が高いかもしれません(@innoSPG最初のコメント)。異なるタイプ及びアレイを含む
別の例は次のようになります。
mylib.f90
subroutine initcom()
implicit none
integer n(2), w !! assumed to be compatible with c_int
real f(2) !! ... with c_float
double precision d(2) !! ... with c_double
common /mycom/ n, f, d, w
print *, "(fort) initializing /mycom/"
n(:) = [ 1, 2 ]
f(:) = [ 3.0, 4.0 ]
d(:) = [ 5.0d0, 6.0d0 ]
w = 7
call printcom()
end
subroutine printcom()
implicit none
integer n(2), w
real f(2)
double precision d(2)
common /mycom/ n, f, d, w
print *, "(fort) current /mycom/"
print *, " n = ", n
print *, " f = ", f
print *, " d = ", d
print *, " w = ", w
end
test.py
from __future__ import print_function
import ctypes
N = 2
class Mycom(ctypes.Structure):
_fields_ = [ ("x", ctypes.c_int * N),
("y", ctypes.c_float * N),
("z", ctypes.c_double * N),
("w", ctypes.c_int ) ]
mylib = ctypes.CDLL("./mylib.so")
mycom = Mycom.in_dll(mylib, "mycom_")
initcom = mylib.initcom_
initcom()
print(" (python) current /mycom/")
print(" x = ", mycom.x[:])
print(" y = ", mycom.y[:])
print(" z = ", mycom.z[:])
print(" w = ", mycom.w )
print(" (python) modifying /mycom/ ...")
for i in range(N):
mycom.x[ i ] = (i + 1) * 10
mycom.y[ i ] = (i + 1) * 100
mycom.z[ i ] = (i + 1) * 0.1
mycom.w = 777
printcom = mylib.printcom_
printcom()
試験:
$ python test.py
(fort) initializing /mycom/
(fort) current /mycom/
n = 1 2
f = 3.0000000 4.0000000
d = 5.0000000000000000 6.0000000000000000
w = 7
(python) current /mycom/
x = [1, 2]
y = [3.0, 4.0]
z = [5.0, 6.0]
w = 7
(python) modifying /mycom/ ...
(fort) current /mycom/
n = 10 20
f = 100.00000 200.00000
d = 0.10000000000000001 0.20000000000000001
w = 777
なぜそれらの変数へのアクセスを得るためにpythonが呼び出せるFortran関数を書かないのですか? – innoSPG
ライブラリは長い間開発されていたので、検証済みのインフラストラクチャの翻訳を避けたいと考えています。共通ブロックの変数にアクセスすると、Python(更新が必要な部分)でそれらを使用し、更新する必要のない何百もの関数をFortranに残すことができます。 – Jfreixa
ラッパーの作成は何かを更新することを意味するものではありません! Fortranのセッターとゲッターを書くだけで、まったく新しいプロシージャーになります。全く変更するものはありません!何百もの機能がそのまま残ることができます。 –