使用c_iso_binding和cython用FORTRAN创建python包



是否可以使用setup.py文件编译python包,该文件使用https://www.fortran90.org/src/best-practices.html#interfacing-with-c中描述的工作流中的fortran代码?

简单地说,这里描述的工作流程是:

  1. 创建fortran包装器函数,为fortran子程序定义c_iso_bindings
  2. 创建一个cython .pyx函数,该函数使用从步骤#1生成的c代码创建一个函数

是否有可能在一个setup.py文件中编译这两个步骤的代码?numpy distutils包似乎最适合编译fortran源代码,而cython是用自己的distutils包编译的。

这个问题的解决方案在setup.py文件中添加了显式的fortran编译器调用,并使用了cython distutils包。这似乎有点混乱,并且引入了使用不同编译器来生成代码的可能性。

似乎numpy具有编译fortran代码并将其链接为库的功能。下面是gfunc在这个问题中的一个最小的工作示例,但是如果有更好的解决方案,我想离开这个问题。

首先,运行cython生成c代码:
cython pygfunc.pyx -3

setup.py文件将fortran代码编译为库,并与生成的cython c代码链接。

from numpy.distutils.misc_util import Configuration
from numpy.distutils.core import setup
def configuration(parent_package='',top_path=None):
config = Configuration('pygfunc', parent_package, top_path)
config.add_library('fort', sources=['gfunc.f90', 'pygfunc.f90'])
config.add_extension('pygfunc', sources=['pygfunc.c'], libraries=['fort'])
return config
if __name__ == '__main__':
setup(configuration=configuration)

这可以通过本地构建进行测试:

python setup.py build_ext --inplace

导航到本地pygfunc文件夹后,下面的测试脚本应该完成,没有异常。

from pygfunc import f
import numpy as np
a = np.linspace(-1, 1, 4) ** 2
A, B = np.meshgrid(a, a, copy=False)
assert(np.allclose(f(1., a=-1., b=1., n=4), np.exp(-(A + B))))

最新更新