将F2PY编译步骤转换为setup.py

时间:2013-02-11 02:53:44

标签: distutils gfortran f2py

我继承了一个Fortran 77代码,该代码实现了几个子程序,这些子程序通过程序块运行,每次运行程序时都需要通过交互式命令提示输入大量用户。由于我想自动运行代码,我将所有子程序移动到一个模块中,并通过F2PY编写了一个包装器代码。经过两步编译后,一切正常:

gfortran -c my_module.f90 -o my_module.o -ffixed-form
f2py -c my_module.o -m my_wrapper my_wrapper.f90

这最终会创建三个文件:my_module.omy_wrapper.omy_module.modmy_wrapper.somy_wrapper.so是我导入Python以访问旧版Fortran代码的模块。

我的目标是将此代码包含在更大的科学代码包中,该代码已经使用setup.py distutils来构建Cython模块。目前完全无视Cython代码,我应该如何将两步构建转换为setup.py中的扩展?我能够弄清楚的关闭看起来像:

from numpy.distutils.core import setup, Extension
wrapper = Extension('my_wrapper', ['my_wrapper.f90', ])
setup(
    libraries = [('my_module', dict(sources=['my_module.f90']],
                                    extra_f90_compile_args=["-ffixed-form", ])))],
    ext_modules = [wrapper, ]
)

但这不起作用。我的编译器在my_module.f90上抛出许多警告,但它仍然编译(如果我使用上面的编译器调用,它不会抛出任何警告)。当它尝试编译包装器时,它找不到my_module.mod,即使它已成功创建。

有什么想法?我有一种感觉,我错过了一些微不足道的东西,但文档似乎没有足够的充实,以表明它可能是什么。

1 个答案:

答案 0 :(得分:5)

可能有点晚,但问题是您在构建my_module时没有在my_wrapper中进行关联:

wrapper = Extension('my_wrapper', sources=['my_wrapper.f90'], libraries=['my_module'])

setup(
    libraries = [('my_module', dict(sources=['my_module.f90'],
                                    extra_f90_compile_args=["-ffixed-form"]))],
    ext_modules = [wrapper]
)

如果my_module仅用于my_wrapper,则只需将其添加到my_wrapper的来源:

wrapper = Extension('my_wrapper', sources=['my_wrapper.f90', 'my_module.f90'],
                                  extra_f90_compile_args=["-ffixed-form"])
setup(
    ext_modules = [wrapper]
)

请注意,这也会将my_module中的所有内容导出到Python,这可能是您不想要的。

我正在处理Python之外的这种双层库结构,使用cmake作为顶级构建系统。我进行了设置,以便make python调用distutils来构建Python包装器。 setup.py可以安全地假设已经构建和安装了所有外部库。如果想要在系统范围内安装通用库,然后为不同的应用程序(例如PythonMatlabOctave,{{1}打包,则此策略是有利的。 },...,它们都有不同的方法来构建扩展。