Python 仅在内部使用派生类型的F2PY wrap过程
很多地方都说F2PY不“支持派生类型”,但我不清楚这是否意味着Python 仅在内部使用派生类型的F2PY wrap过程,python,numpy,fortran,f2py,Python,Numpy,Fortran,F2py,很多地方都说F2PY不“支持派生类型”,但我不清楚这是否意味着 派生类型不能用作由包装的过程的参数 F2PY 在我想用F2PY包装的过程中,派生类型甚至不能在内部使用 在我的用例中,第一点是一个不便,但第二点是一个交易破坏者 作为一个例子,考虑这个计算向量和的模块: module derived_types implicit none public :: point, add type :: point real :: x real :: y end type point
- 派生类型不能用作由包装的过程的参数 F2PY
- 在我想用F2PY包装的过程中,派生类型甚至不能在内部使用
作为一个例子,考虑这个计算向量和的模块:
module derived_types
implicit none
public :: point, add
type :: point
real :: x
real :: y
end type point
contains
type(point) function add(p1, p2)
type(point), intent(in) :: p1
type(point), intent(in) :: p2
add%x = p1%x + p2%x
add%y = p1%y + p2%y
end function add
end module derived_types
module expose
use derived_types, only: point, add
implicit none
contains
subroutine vector_sum(x1, y1, x2, y2, x3, y3)
real, intent(in) :: x1, y1, x2, y2
real, intent(out) :: x3, y3
type(point) :: p1, p2, p3
p1 = point(x1, y1)
p2 = point(x2, y2)
p3 = add(p1, p2)
x3 = p3%x
y3 = p3%y
end subroutine vector_sum
end module expose
子程序vector\u sum
应向Python公开。派生类型点
不能在Python和Fortran之间传递
这与普通Fortran程序一样工作(添加了适当的程序块),但F2PY失败:
f2py-c ff.f90仅限:向量和
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 "untitled" sources
f2py options: ['only:', 'vector_sum', ':']
f2py:> /tmp/tmpjdq8b9dq/src.linux-x86_64-3.8/untitledmodule.c
creating /tmp/tmpjdq8b9dq/src.linux-x86_64-3.8
Reading fortran codes...
Reading file 'ff.f90' (format:free)
Line #7 in ff.f90:"type :: point "
analyzeline: No name/args pattern found for line.
Post-processing...
Block: untitled
Block: derived_types
Block: unknown_type
Block: expose
Block: vector_sum
Block: run
Post-processing (stage 2)...
Block: untitled
Block: unknown_interface
Block: derived_types
Block: unknown_type
Block: expose
Block: vector_sum
Block: run
Building modules...
Building module "untitled"...
Constructing F90 module support for "derived_types"...
Variables: point add
getctype: No C-type found in "{'attrspec': ['public']}", assuming void.
Traceback (most recent call last):
File "/home/me/.pyenv/versions/anaconda3-2020.11/lib/python3.8/site-packages/numpy/f2py/f90mod_rules.py", line 143, in buildhooks
at = capi_maps.c2capi_map[ct]
KeyError: 'void'
使用F2PY可以完成这样的事情吗?您可以使用单个过程,定义其中的派生类型以及包含的过程。 这是一种快速而肮脏的方法,只适用于较小的问题 下面是一个示例实现
! file: a.f90
subroutine vector_sum(x1, y1, x2, y2, x3, y3)
real, intent(in) :: x1, y1, x2, y2
real, intent(out) :: x3, y3
type point
real :: x(2)
end type
type(point) :: p1, p2, p3
p1%x = [x1, y1]
p2%x = [x2, y2]
p3 = add(p1, p2)
x3 = p3%x(1)
y3 = p3%x(2)
contains
type(point) function add(p1, p2)
type(point), intent(in) :: p1
type(point), intent(in) :: p2
add%x = p1%x + p2%x
end function
end subroutine
汇编
$f2py-c a.f90-m amod
python中的用法
导入amod
>>>amod.向量_和(1,2,3,4)
(4.0, 6.0)
经过一些修改,我认为首先将定义所有派生类型的代码编译到静态库中可能是最简单的,即:
libff.f90
包含:
module derived_types
implicit none
public :: point, add
type :: point
real :: x
real :: y
end type point
contains
type(point) function add(p1, p2)
type(point), intent(in) :: p1
type(point), intent(in) :: p2
add%x = p1%x + p2%x
add%y = p1%y + p2%y
end function add
end module derived_types
module expose
use derived_types, only: point, add
implicit none
contains
subroutine vector_sum(x1, y1, x2, y2, x3, y3)
real, intent(in) :: x1, y1, x2, y2
real, intent(out) :: x3, y3
type(point) :: p1, p2, p3
p1 = point(x1, y1)
p2 = point(x2, y2)
p3 = add(p1, p2)
x3 = p3%x
y3 = p3%y
end subroutine vector_sum
end module expose
使用gfortran-free-c libff.f90编译以生成libff.o
然后,在链接库时,可以使用F2PY编译使用预编译模块派生类型的代码,即:
ff.f90
包含:
module derived_types
implicit none
public :: point, add
type :: point
real :: x
real :: y
end type point
contains
type(point) function add(p1, p2)
type(point), intent(in) :: p1
type(point), intent(in) :: p2
add%x = p1%x + p2%x
add%y = p1%y + p2%y
end function add
end module derived_types
module expose
use derived_types, only: point, add
implicit none
contains
subroutine vector_sum(x1, y1, x2, y2, x3, y3)
real, intent(in) :: x1, y1, x2, y2
real, intent(out) :: x3, y3
type(point) :: p1, p2, p3
p1 = point(x1, y1)
p2 = point(x2, y2)
p3 = add(p1, p2)
x3 = p3%x
y3 = p3%y
end subroutine vector_sum
end module expose
在使用F2PY构建带有F2PY-cf.f90 libff.o-m ff
的Python扩展之后,我们可以使用从ff.expose import vector\u sum
在Python中导入它
经验教训:将派生类型的定义放入预编译库中,然后使用F2PY仅编译使用这些类型的代码。这可以工作并回答问题(+1),但会阻止派生类型在不同的子例程之间共享。您可以在包含的过程之间传递对象。但这可能对更大的项目用途有限。。。