【问题标题】:creating a python package with fortran using c_iso_binding and cython使用 c_iso_binding 和 cython 创建一个带有 fortran 的 python 包
【发布时间】:2021-08-27 18:47:38
【问题描述】:

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

简而言之,这里描述的工作流程是:

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

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

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

【问题讨论】:

  • 不幸的是,我认为不可能以可移植的方式进行,但如果它仅适用于 linux 或 mac,您可以通过添加指向预编译的 fortran 二进制文件的自定义链接参数来实现( -L/path/to/file -lyour_lib -Wl,-rpath=/path/to/file) 用于 C 扩展。 fortran 代码仍然需要通过 numpy 单独编译。

标签: python numpy fortran cython


【解决方案1】:

似乎 numpy 具有编译 fortran 代码并将其作为库链接的功能。这是this question 中 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))))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    相关资源
    最近更新 更多