6

我继承了一个 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.so. 这my_wrapper.so是我导入 Python 以访问旧版 Fortran 代码的模块。

我的目标是将此代码包含在更大的科学代码包中,该代码包已经setup.py用于distutils构建 Cython 模块。暂时完全忽略了 Cython 代码,我应该如何将 2 步构建转换为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,即使它已成功创建,它也找不到 .

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

4

1 回答 1

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_moduleis for 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 包装器。s 可以安全地假设所有外部库setup.py都已构建和安装。如果想要拥有在系统范围内安装的通用库,然后为不同的应用程序(例如PythonMatlabOctaveIDL......)包装,这种策略是有利的,这些应用程序都有不同的方式来构建扩展。

于 2013-05-12T08:57:01.503 回答