A)這種方法試驗&錯誤後,似乎下面的代碼工作與python3.5/gfortran4.8/cython0.25在Linux x86_64的,所以你可以試試看它是否有效......?
fort.f90:
module mymod
use iso_c_binding
implicit none
contains
subroutine fortsub() bind(c)
double precision x(2)
real y(3)
real z(4)
integer n(5)
common /mycom/ x, y, z, n
data z/100.0, 200.0, 300.0, 400.0/!! initialize only z(:) (for check)
print *, "(fort) x(:) = ", x(:)
print *, "(fort) y(:) = ", y(:)
print *, "(fort) z(:) = ", z(:)
print *, "(fort) n(:) = ", n(:)
end subroutine
end module
fort.h:
extern void fortsub(void); /* or fortsub_() if bind(c) is not used */
extern struct Mycom {
double x[ 2 ];
float y[ 3 ];
float z[ 4 ];
int n[ 5 ];
} mycom_;
test.pyx:
cdef extern from "fort.h":
void fortsub()
struct Mycom:
double x[ 2 ]
float y[ 3 ]
int n[ 5 ]
Mycom mycom_;
def go():
mycom_.x[:] = [ 1.0, 2.0 ]
mycom_.y[:] = [ 11.0, 12.0, 13.0 ]
mycom_.n[:] = [ 1, 2, 3, 4, 5 ]
fortsub()
setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
from os import system
system('gfortran -c fort.f90 -o fort.o -fPIC')
ext_modules = [Extension('test', ['test.pyx'],
extra_compile_args = ['-fPIC'],
extra_link_args = ['fort.o', '-lgfortran'])]
setup(name = 'test',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules)
編譯:
$ python setup.py build_ext --inplace
測試:
$ python
>>> import test
>>> test.go()
(fort) x(:) = 1.0000000000000000 2.0000000000000000
(fort) y(:) = 11.0000000 12.0000000 13.0000000
(fort) z(:) = 100.000000 200.000000 300.000000 400.000000
(fort) n(:) = 1 2 3 4 5
在這裏,請注意,我並沒有包括在z
到test.pyx
檢查我們是否可以在公共塊聲明唯一入選的變量。此外,有些編譯器選項可能需要使C和Fortran之間的公共變量對齊一致(this YoLinux page可能有用)。
B)我想這將取決於由Fortran程序peformed計算量...如果例程重(至少需要幾分鐘),在吸氣複製操作/ setter方法可能沒有問題。另一方面,如果程序快速完成而被稱爲大量次數,則開銷可能不可忽略...
爲了提高效率,將指針變量從Cython傳遞到Fortran可能很有用,get所選的common
變量的地址由c_loc()
以某種方式被選中,並通過Cython端的指針直接訪問它們(雖然不能確定它是否工作......)但是如果沒有內存對齊的問題(對於使用的編譯器),它可能比以上更直接地使用結構。
與使用Cython進行封裝相比,使用'f2py'封裝可能更容易。在[scipy f2py使用頁面](https://docs.scipy.org/doc/numpy-dev/f2py/python-usage.html)上有一些示例用法。 – mgilson
我已經將F2PY用於其他庫。它運行良好,並且提供對公共塊數據的訪問。但是,在其他項目中,我鏈接到使用fortran派生類型的代碼,這是F2PY無法處理的,但很容易在Cython中使用。所以我一直在尋找一個Cython解決方案。 – tharen