主 .f90 模块调用特定 .f 文件的问题 运行 f2py? (unknown_subroutine?)
Issues running f2py with main .f90 module calling specific .f file? (unknown_subroutine?)
我正在尝试使用 f2py 将 Fortran 函数与我的主要 python 代码集成。但是,当我尝试包含特定的“.f”文件时,f2py 会引发错误(但可以与其他“.f”文件一起正常工作)。我已经为我的主“.f90”文件创建了以下最小工作示例:
module min_example
implicit none
public :: calc_min
contains
subroutine calc_min
print*, 'test'
return
end subroutine calc_min
end module min_example
导致我出现问题的“.f”文件是 'qromb.f',如下所示:https://github.com/david-deboer/cosmo/blob/master/Komatsu/mf_jenkins/qromb.f
The error looks like this (sorry for the huge block - I'm new to this and not sure what is relevant):
running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "min_example" sources
f2py options: []
f2py:> /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c
creating /tmp/tmpQULhjN/src.linux-x86_64-2.7
Reading fortran codes...
Reading file 'qromb.f' (format:fix,strict)
Line #1 in qromb.f:" SUBROUTINE qromb(func,a,b,ss,q) ! one parameter"
analyzeline: No name/args pattern found for line.
Line #22 in qromb.f:" SUBROUTINE trapzd(func,a,b,s,n,q) ! one paramete"
analyzeline: No name/args pattern found for line.
Reading file 'min_example.f90' (format:free)
Post-processing...
Block: min_example
Block: unknown_subroutine
Block: unknown_subroutine
Block: polint
Block: min_example
Block: calc_min
Post-processing (stage 2)...
Block: min_example
Block: unknown_interface
Block: unknown_subroutine
Block: unknown_subroutine
Block: polint
Block: min_example
Block: calc_min
Building modules...
Building module "min_example"...
Constructing wrapper function "unknown_subroutine"...
unknown_subroutine()
Constructing wrapper function "unknown_subroutine"...
unknown_subroutine()
Constructing wrapper function "polint"...
polint(xa,ya,x,y,dy,[n])
Constructing F90 module support for "min_example"...
Constructing wrapper function "min_example.calc_min"...
calc_min()
Wrote C/API module "min_example" to file "/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c"
Fortran 90 wrappers are saved to "/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_example-f2pywrappers2.f90"
adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.c' to sources.
adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7' to include_dirs.
copying /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.c -> /tmp/tmpQULhjN/src.linux-x86_64-2.7
copying /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.h -> /tmp/tmpQULhjN/src.linux-x86_64-2.7
adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_example-f2pywrappers2.f90' to sources.
build_src: building npy-pkg config files
running build_ext
customize UnixCCompiler
customize UnixCCompiler using build_ext
customize Gnu95FCompiler
Found executable /usr/bin/gfortran
customize Gnu95FCompiler
customize Gnu95FCompiler using build_ext
building 'min_example' extension
compiling C sources
C compiler: gcc -pthread -B /home/anasal/anaconda2/compiler_compat -Wl,--sysroot=/ -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC
creating /tmp/tmpQULhjN/tmp
creating /tmp/tmpQULhjN/tmp/tmpQULhjN
creating /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7
compile options: '-I/tmp/tmpQULhjN/src.linux-x86_64-2.7 -I/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include -I/home/anasal/anaconda2/include/python2.7 -c'
gcc: /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c
In file included from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.h:13,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:19:
/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
#warning "Using deprecated NumPy API, disable it by " \
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:288:13: error: redefinition of ‘doc_f2py_rout_min_example_unknown_subroutine’
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: note: previous definition of ‘doc_f2py_rout_min_example_unknown_subroutine’ was here
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:292:18: error: redefinition of ‘f2py_rout_min_example_unknown_subroutine’
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: note: previous definition of ‘f2py_rout_min_example_unknown_subroutine’ was here
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:112:12: warning: ‘f2py_size’ defined but not used [-Wunused-function]
static int f2py_size(PyArrayObject* var, ...)
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: warning: ‘doc_f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-variable]
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: warning: ‘f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-function]
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
In file included from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.h:13,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:19:
/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
#warning "Using deprecated NumPy API, disable it by " \
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:288:13: error: redefinition of ‘doc_f2py_rout_min_example_unknown_subroutine’
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: note: previous definition of ‘doc_f2py_rout_min_example_unknown_subroutine’ was here
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:292:18: error: redefinition of ‘f2py_rout_min_example_unknown_subroutine’
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: note: previous definition of ‘f2py_rout_min_example_unknown_subroutine’ was here
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:112:12: warning: ‘f2py_size’ defined but not used [-Wunused-function]
static int f2py_size(PyArrayObject* var, ...)
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: warning: ‘doc_f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-variable]
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: warning: ‘f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-function]
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
error: Command "gcc -pthread -B /home/anasal/anaconda2/compiler_compat -Wl,--sysroot=/ -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/tmp/tmpQULhjN/src.linux-x86_64-2.7 -I/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include -I/home/anasal/anaconda2/include/python2.7 -c /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c -o /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.o -MMD -MF /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.o.d" failed with exit status 1
我使用以下方法编译它:
gfortran -c min_example.f90
gfortran -c qromb.f
f2py -c qromb.f min_example.f90 -m min_example
非常感谢任何帮助!谢谢!
更新:我继续四处寻找,发现的线索很少。有人建议 f2py 的内联注释有问题,但删除它们并没有帮助。我读到的另一个答案建议将“.f”文件转换为“.f90”文件,但老实说,我不知道两者之间的区别(我对 Fortran 很陌生)。所以我不知道该怎么做(.f 文件的结构对我来说不是很清楚)而且我不知道它是否会减慢它的速度。
另一个更新:使用 'f2py -m min_example min_example.f90 qromb.f' 编译给出以下输出:
Reading fortran codes...
Reading file 'min_example.f90' (format:free)
Reading file 'qromb.f' (format:fix,strict)
Post-processing...
Block: min_example
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: func
Block: polint
Post-processing (stage 2)...
Block: min_example
Block: unknown_interface
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: polint
Building modules...
Constructing call-back function "cb_func_in_trapzd__user__routines"
def func(x,q): return sum
Building module "min_example"...
Constructing wrapper function "qromb"...
routsign2map: Confused: function qromb has externals ['func'] but no "use" statement.
sign2map: Confused: external func is not in lcb_map[].
append_needs: unknown need 'func'
append_needs: unknown need 'func'
qromb(func,a,b,ss,q,[func_extra_args])
Constructing wrapper function "trapzd"...
trapzd(func,a,b,s,n,q,[func_extra_args])
Constructing wrapper function "polint"...
polint(xa,ya,x,y,dy,[n])
Constructing F90 module support for "min_example"...
Constructing wrapper function "min_example.calc_min"...
calc_min()
Wrote C/API module "min_example" to file "./min_examplemodule.c"
Fortran 90 wrappers are saved to "./min_example-f2pywrappers2.f90"
并生成以下文件:
min_example-f2pywrappers2.f90
min_example.mod
min_example.o
qromb.o
min_examplemodule.c
这看起来很有希望,但是当我进入 python 时,我无法导入函数。
为了让 F2PY 为 Fortran 过程创建包装器,它需要完全识别 Fortran 过程参数的类型和意图,即参数是 integer/real、scalar/vector、input/output/both,等等。这个 Fortran interface 在 F2PY 中被称为程序的 signature。如果函数作为参数传递(例如 trapzd
中的 func
和链接文件 qromb.f
中的 qromb
),F2PY 还需要为传递的函数的参数识别此信息.不同于例如Fortran 90 及之后的版本,Fortran 77(qromb.f
似乎是用的方言)没有提供任何语言直接在 Fortran 代码中显式定义这些信息。
因此,在您的案例中,F2PY 未能自动 使用手头的信息识别程序签名(因此 unknown_subroutine 输出)。
但是,F2PY 可以通过多种方式成功包装您的代码:
- 协助 F2PY 识别过程签名,通过创建和
手动修改
qromb.f
. 的过程签名文件
- 定义接口并使用例如
qromb
在你的
min_example
模块,并将您的 Fortran 77 代码作为
预编译对象到 F2PY。参见例如这个的第一部分
answer。
- 用更现代的 Fortran 方言重写
qromb.f
,
显式定义所有接口(您的代码似乎被修改
来自 Fortran 77 中的数字食谱,其中有 Fortran 90
版本存在,可能会有帮助)。
您提到您是 Fortran 新手,因此可能不想直接修改您的源代码。考虑到这一点,我将更详细地描述上面列出的第一个解决方案,并将其应用于您的示例:
第一步是创建签名文件(参见F2PY documentation中的聪明的方法),执行以下命令:
f2py -m min_example -h min_example.pyf min_example.f90 qromb.f
这会创建一个名为 min_example.pyf
的签名文件,打开此文件您会注意到 Fortran 接口 (F2PY signatures) 到 trapzd
和 qromb
仅显示为 unknown_subroutine
。此外,polint
的接口需要修改。
您的第二步是修改 min_example.pyf
,使其仅包含以下文本(另请参阅 F2Py documentation on call-back functions):
! -*- f90 -*-
! Note: the context of this file is case sensitive.
python module __user__routines
interface
function fun(x,q) result(res) ! in :min_example:qromb.f
real*8 intent(in) :: x, q
real*8 :: res
end function fun
end interface
end python module __user__routines
python module min_example ! in
interface ! in :min_example
module min_example ! in :min_example:min_example.f90
subroutine calc_min ! in :min_example:min_example.f90:min_example
end subroutine calc_min
end module min_example
subroutine qromb(func,a,b,ss,q) ! in :min_example:qromb.f
use __user__routines, func=>fun
external func
real*8 intent(in) :: a, b, q
real*8 intent(out) :: ss
end subroutine qromb
subroutine trapzd(func,a,b,s,n,q) ! in :min_example:qromb.f
use __user__routines, func=>fun
external func
real*8 intent(in) :: a, b, q
integer intent(in) :: n
real*8 intent(inout) :: s
end subroutine trapzd
subroutine polint(xa,ya,n,x,y,dy) ! in :min_example:qromb.f
real*8 dimension(n),intent(in) :: xa
real*8 dimension(n),intent(in),depend(n) :: ya
integer, optional,intent(in),check(len(xa)>=n),depend(xa) :: n=len(xa)
real*8 intent(in) :: x
real*8 intent(out) :: y, dy
end subroutine polint
end interface
end python module min_example
! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/
第三步也是最后一步是使用 F2PY 和手动更正的签名文件编译源代码,方法是执行以下命令:
f2py -c min_example.pyf min_example.f90 qromb.f
您的示例没有显示您打算如何使用 Python 中的 Fortran 代码,但这里有一个示例 Python 脚本,显示了使用刚刚编译的模块:
import numpy as np
from scipy.integrate import romberg
import min_example
print(min_example.__doc__)
print(min_example.qromb.__doc__)
def func(x, q):
return q*np.sin(x)
a = 0.0
b = np.pi
q = 1.0
f_f2py = min_example.qromb(func, a, b, q)
f_scipy = romberg(func, a, b, args=(q,))
print("f2py: {:0.7g}".format(f_f2py))
print("scipy: {:0.7g}".format(f_scipy))
这给了我以下输出:
<auto-generated documentation strings>
f2py: 2
scipy: 2
我正在尝试使用 f2py 将 Fortran 函数与我的主要 python 代码集成。但是,当我尝试包含特定的“.f”文件时,f2py 会引发错误(但可以与其他“.f”文件一起正常工作)。我已经为我的主“.f90”文件创建了以下最小工作示例:
module min_example
implicit none
public :: calc_min
contains
subroutine calc_min
print*, 'test'
return
end subroutine calc_min
end module min_example
导致我出现问题的“.f”文件是 'qromb.f',如下所示:https://github.com/david-deboer/cosmo/blob/master/Komatsu/mf_jenkins/qromb.f
The error looks like this (sorry for the huge block - I'm new to this and not sure what is relevant):
running build
running config_cc
unifing config_cc, config, build_clib, build_ext, build commands --compiler options
running config_fc
unifing config_fc, config, build_clib, build_ext, build commands --fcompiler options
running build_src
build_src
building extension "min_example" sources
f2py options: []
f2py:> /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c
creating /tmp/tmpQULhjN/src.linux-x86_64-2.7
Reading fortran codes...
Reading file 'qromb.f' (format:fix,strict)
Line #1 in qromb.f:" SUBROUTINE qromb(func,a,b,ss,q) ! one parameter"
analyzeline: No name/args pattern found for line.
Line #22 in qromb.f:" SUBROUTINE trapzd(func,a,b,s,n,q) ! one paramete"
analyzeline: No name/args pattern found for line.
Reading file 'min_example.f90' (format:free)
Post-processing...
Block: min_example
Block: unknown_subroutine
Block: unknown_subroutine
Block: polint
Block: min_example
Block: calc_min
Post-processing (stage 2)...
Block: min_example
Block: unknown_interface
Block: unknown_subroutine
Block: unknown_subroutine
Block: polint
Block: min_example
Block: calc_min
Building modules...
Building module "min_example"...
Constructing wrapper function "unknown_subroutine"...
unknown_subroutine()
Constructing wrapper function "unknown_subroutine"...
unknown_subroutine()
Constructing wrapper function "polint"...
polint(xa,ya,x,y,dy,[n])
Constructing F90 module support for "min_example"...
Constructing wrapper function "min_example.calc_min"...
calc_min()
Wrote C/API module "min_example" to file "/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c"
Fortran 90 wrappers are saved to "/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_example-f2pywrappers2.f90"
adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.c' to sources.
adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7' to include_dirs.
copying /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.c -> /tmp/tmpQULhjN/src.linux-x86_64-2.7
copying /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/f2py/src/fortranobject.h -> /tmp/tmpQULhjN/src.linux-x86_64-2.7
adding '/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_example-f2pywrappers2.f90' to sources.
build_src: building npy-pkg config files
running build_ext
customize UnixCCompiler
customize UnixCCompiler using build_ext
customize Gnu95FCompiler
Found executable /usr/bin/gfortran
customize Gnu95FCompiler
customize Gnu95FCompiler using build_ext
building 'min_example' extension
compiling C sources
C compiler: gcc -pthread -B /home/anasal/anaconda2/compiler_compat -Wl,--sysroot=/ -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC
creating /tmp/tmpQULhjN/tmp
creating /tmp/tmpQULhjN/tmp/tmpQULhjN
creating /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7
compile options: '-I/tmp/tmpQULhjN/src.linux-x86_64-2.7 -I/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include -I/home/anasal/anaconda2/include/python2.7 -c'
gcc: /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c
In file included from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.h:13,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:19:
/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
#warning "Using deprecated NumPy API, disable it by " \
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:288:13: error: redefinition of ‘doc_f2py_rout_min_example_unknown_subroutine’
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: note: previous definition of ‘doc_f2py_rout_min_example_unknown_subroutine’ was here
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:292:18: error: redefinition of ‘f2py_rout_min_example_unknown_subroutine’
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: note: previous definition of ‘f2py_rout_min_example_unknown_subroutine’ was here
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:112:12: warning: ‘f2py_size’ defined but not used [-Wunused-function]
static int f2py_size(PyArrayObject* var, ...)
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: warning: ‘doc_f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-variable]
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: warning: ‘f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-function]
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
In file included from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarraytypes.h:1809:0,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h:18,
from /home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/arrayobject.h:4,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/fortranobject.h:13,
from /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:19:
/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include/numpy/npy_1_7_deprecated_api.h:15:2: warning: #warning "Using deprecated NumPy API, disable it by " "#defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
#warning "Using deprecated NumPy API, disable it by " \
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:288:13: error: redefinition of ‘doc_f2py_rout_min_example_unknown_subroutine’
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: note: previous definition of ‘doc_f2py_rout_min_example_unknown_subroutine’ was here
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:292:18: error: redefinition of ‘f2py_rout_min_example_unknown_subroutine’
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: note: previous definition of ‘f2py_rout_min_example_unknown_subroutine’ was here
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:112:12: warning: ‘f2py_size’ defined but not used [-Wunused-function]
static int f2py_size(PyArrayObject* var, ...)
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:228:13: warning: ‘doc_f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-variable]
static char doc_f2py_rout_min_example_unknown_subroutine[] = "\
^
/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c:232:18: warning: ‘f2py_rout_min_example_unknown_subroutine’ defined but not used [-Wunused-function]
static PyObject *f2py_rout_min_example_unknown_subroutine(const PyObject *capi_self,
^
error: Command "gcc -pthread -B /home/anasal/anaconda2/compiler_compat -Wl,--sysroot=/ -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/tmp/tmpQULhjN/src.linux-x86_64-2.7 -I/home/anasal/anaconda2/lib/python2.7/site-packages/numpy/core/include -I/home/anasal/anaconda2/include/python2.7 -c /tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.c -o /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.o -MMD -MF /tmp/tmpQULhjN/tmp/tmpQULhjN/src.linux-x86_64-2.7/min_examplemodule.o.d" failed with exit status 1
我使用以下方法编译它:
gfortran -c min_example.f90
gfortran -c qromb.f
f2py -c qromb.f min_example.f90 -m min_example
非常感谢任何帮助!谢谢!
更新:我继续四处寻找,发现的线索很少。有人建议 f2py 的内联注释有问题,但删除它们并没有帮助。我读到的另一个答案建议将“.f”文件转换为“.f90”文件,但老实说,我不知道两者之间的区别(我对 Fortran 很陌生)。所以我不知道该怎么做(.f 文件的结构对我来说不是很清楚)而且我不知道它是否会减慢它的速度。
另一个更新:使用 'f2py -m min_example min_example.f90 qromb.f' 编译给出以下输出:
Reading fortran codes...
Reading file 'min_example.f90' (format:free)
Reading file 'qromb.f' (format:fix,strict)
Post-processing...
Block: min_example
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: func
Block: polint
Post-processing (stage 2)...
Block: min_example
Block: unknown_interface
Block: min_example
Block: calc_min
Block: qromb
Block: trapzd
Block: polint
Building modules...
Constructing call-back function "cb_func_in_trapzd__user__routines"
def func(x,q): return sum
Building module "min_example"...
Constructing wrapper function "qromb"...
routsign2map: Confused: function qromb has externals ['func'] but no "use" statement.
sign2map: Confused: external func is not in lcb_map[].
append_needs: unknown need 'func'
append_needs: unknown need 'func'
qromb(func,a,b,ss,q,[func_extra_args])
Constructing wrapper function "trapzd"...
trapzd(func,a,b,s,n,q,[func_extra_args])
Constructing wrapper function "polint"...
polint(xa,ya,x,y,dy,[n])
Constructing F90 module support for "min_example"...
Constructing wrapper function "min_example.calc_min"...
calc_min()
Wrote C/API module "min_example" to file "./min_examplemodule.c"
Fortran 90 wrappers are saved to "./min_example-f2pywrappers2.f90"
并生成以下文件:
min_example-f2pywrappers2.f90
min_example.mod
min_example.o
qromb.o
min_examplemodule.c
这看起来很有希望,但是当我进入 python 时,我无法导入函数。
为了让 F2PY 为 Fortran 过程创建包装器,它需要完全识别 Fortran 过程参数的类型和意图,即参数是 integer/real、scalar/vector、input/output/both,等等。这个 Fortran interface 在 F2PY 中被称为程序的 signature。如果函数作为参数传递(例如 trapzd
中的 func
和链接文件 qromb.f
中的 qromb
),F2PY 还需要为传递的函数的参数识别此信息.不同于例如Fortran 90 及之后的版本,Fortran 77(qromb.f
似乎是用的方言)没有提供任何语言直接在 Fortran 代码中显式定义这些信息。
因此,在您的案例中,F2PY 未能自动 使用手头的信息识别程序签名(因此 unknown_subroutine 输出)。
但是,F2PY 可以通过多种方式成功包装您的代码:
- 协助 F2PY 识别过程签名,通过创建和
手动修改
qromb.f
. 的过程签名文件
- 定义接口并使用例如
qromb
在你的min_example
模块,并将您的 Fortran 77 代码作为 预编译对象到 F2PY。参见例如这个的第一部分 answer。 - 用更现代的 Fortran 方言重写
qromb.f
, 显式定义所有接口(您的代码似乎被修改 来自 Fortran 77 中的数字食谱,其中有 Fortran 90 版本存在,可能会有帮助)。
您提到您是 Fortran 新手,因此可能不想直接修改您的源代码。考虑到这一点,我将更详细地描述上面列出的第一个解决方案,并将其应用于您的示例:
第一步是创建签名文件(参见F2PY documentation中的聪明的方法),执行以下命令:
f2py -m min_example -h min_example.pyf min_example.f90 qromb.f
这会创建一个名为 min_example.pyf
的签名文件,打开此文件您会注意到 Fortran 接口 (F2PY signatures) 到 trapzd
和 qromb
仅显示为 unknown_subroutine
。此外,polint
的接口需要修改。
您的第二步是修改 min_example.pyf
,使其仅包含以下文本(另请参阅 F2Py documentation on call-back functions):
! -*- f90 -*-
! Note: the context of this file is case sensitive.
python module __user__routines
interface
function fun(x,q) result(res) ! in :min_example:qromb.f
real*8 intent(in) :: x, q
real*8 :: res
end function fun
end interface
end python module __user__routines
python module min_example ! in
interface ! in :min_example
module min_example ! in :min_example:min_example.f90
subroutine calc_min ! in :min_example:min_example.f90:min_example
end subroutine calc_min
end module min_example
subroutine qromb(func,a,b,ss,q) ! in :min_example:qromb.f
use __user__routines, func=>fun
external func
real*8 intent(in) :: a, b, q
real*8 intent(out) :: ss
end subroutine qromb
subroutine trapzd(func,a,b,s,n,q) ! in :min_example:qromb.f
use __user__routines, func=>fun
external func
real*8 intent(in) :: a, b, q
integer intent(in) :: n
real*8 intent(inout) :: s
end subroutine trapzd
subroutine polint(xa,ya,n,x,y,dy) ! in :min_example:qromb.f
real*8 dimension(n),intent(in) :: xa
real*8 dimension(n),intent(in),depend(n) :: ya
integer, optional,intent(in),check(len(xa)>=n),depend(xa) :: n=len(xa)
real*8 intent(in) :: x
real*8 intent(out) :: y, dy
end subroutine polint
end interface
end python module min_example
! This file was auto-generated with f2py (version:2).
! See http://cens.ioc.ee/projects/f2py2e/
第三步也是最后一步是使用 F2PY 和手动更正的签名文件编译源代码,方法是执行以下命令:
f2py -c min_example.pyf min_example.f90 qromb.f
您的示例没有显示您打算如何使用 Python 中的 Fortran 代码,但这里有一个示例 Python 脚本,显示了使用刚刚编译的模块:
import numpy as np
from scipy.integrate import romberg
import min_example
print(min_example.__doc__)
print(min_example.qromb.__doc__)
def func(x, q):
return q*np.sin(x)
a = 0.0
b = np.pi
q = 1.0
f_f2py = min_example.qromb(func, a, b, q)
f_scipy = romberg(func, a, b, args=(q,))
print("f2py: {:0.7g}".format(f_f2py))
print("scipy: {:0.7g}".format(f_scipy))
这给了我以下输出:
<auto-generated documentation strings>
f2py: 2
scipy: 2