我继承了一个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.o
,my_wrapper.o
,my_module.mod
和my_wrapper.so
。 my_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
,即使它已成功创建。
有什么想法?我有一种感觉,我错过了一些微不足道的东西,但文档似乎没有足够的充实,以表明它可能是什么。
答案 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
可以安全地假设已经构建和安装了所有外部库。如果想要在系统范围内安装通用库,然后为不同的应用程序(例如Python
,Matlab
,Octave
,{{1}打包,则此策略是有利的。 },...,它们都有不同的方法来构建扩展。