Python 仅在内部使用派生类型的F2PY wrap过程

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
  • 在我想用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),但会阻止派生类型在不同的子例程之间共享。您可以在包含的过程之间传递对象。但这可能对更大的项目用途有限。。。