我在f2py
中的可分配数组上遇到问题。在下面的代码(存储在mymod.f90
中)中,我创建了两个模块vars
和worker
:
vars
存储并分配数组b
worker
包含与vars
中的该数组一起使用的子例程。第一个worker
子例程将标量添加到b
。这按预期工作。问题在于下一个例程,该例程应向数组b
添加一个匹配第一维的向量。已实现的子例程add_vector2
可以工作,但是需要传递输入vector
的尺寸。
我需要的是一个仅将向量作为参数的子例程,例如注释掉的子例程add_vector1
。但是,这不能用f2py
编译(但可以和gfortran
一起编译)。
代码如下:
! =======================================
! MODULE TO STORE AND INTIALIZE VARIABLES
! =======================================
MODULE VARS
IMPLICIT NONE
SAVE
INTEGER :: n1, n2
DOUBLEPRECISION, ALLOCATABLE:: b(:,:)
CONTAINS
SUBROUTINE ALLOC(n1in, n2in)
IMPLICIT NONE
INTEGER, INTENT(IN) :: n1in, n2in
INTEGER :: i, j
n1 = n1in
n2 = n2in
IF (ALLOCATED(b)) DEALLOCATE(b)
ALLOCATE(b(n1,n2))
b = 0d0
DO i = 1, n1
DO j = 1, n2
b(i, j) = (i-1)*n2 + j
ENDDO
ENDDO
END SUBROUTINE ALLOC
END MODULE VARS
! ===================================
! MODULE THAT PROCESSES THE VARIABLES
! ===================================
MODULE worker
IMPLICIT NONE
CONTAINS
! ADD A SCALAR TO ALL VALUES
SUBROUTINE add_scalar(x)
USE vars, ONLY: b, n1, n2
IMPLICIT NONE
doubleprecision, INTENT(in) :: x
INTEGER :: i, j
DO i = 1, n1
DO j = 1, n2
b(i,j) = b(i,j) + x
ENDDO
ENDDO
END SUBROUTINE add_scalar
! ADD A VECTOR TO EVERY ROW
! THIS ONE WORKS, but needs the dimension
! of the vector as input. Instead, it should
! use n1 for variables
SUBROUTINE add_vector2(vector,n1in)
USE vars, ONLY: b, n2
IMPLICIT NONE
integer, INTENT(IN) :: n1in
doubleprecision, INTENT(in) :: vector(n1in)
INTEGER :: i, j
DO i = 1, n1in
DO j = 1, n2
b(i,j) = b(i,j) + vector(i)
ENDDO
ENDDO
END SUBROUTINE add_vector2
! ADD A VECTOR TO EVERY ROW
! the call of this routine should not
! have any other arguments, the vector
! is supposed to have the right shape n1
!SUBROUTINE add_vector1(vector)
! USE vars, ONLY: b, n1, n2
! IMPLICIT NONE
! doubleprecision, INTENT(in) :: vector(n1)
! INTEGER :: i, j
! DO i = 1, n1
! DO j = 1, n2
! b(i,j) = b(i,j) + vector(i)
! ENDDO
! ENDDO
!END SUBROUTINE add_vector1
END MODULE worker
可以使用
进行编译f2py -m mymod -c mymod.f90
在python中:
In [1]: import mymod
In [2]: mymod.vars.alloc(3,2)
In [3]: mymod.vars.b
Out[3]:
array([[1., 2.],
[3., 4.],
[5., 6.]])
In [4]: mymod.worker.add_vector2([1,2,3])
In [5]: mymod.vars.b
Out[5]:
array([[2., 3.],
[5., 6.],
[8., 9.]])
如何使add_vector1
(具有相同的参数/调用)与f2py
一起使用?
编辑1:
这是来自f2py
的错误消息:
#warning "Using deprecated NumPy API, disable it by " \
^
/var/folders/r_/b16rpth9643dx5csqdw29wn40000gn/T/tmpm_sqc9ce/src.macosx-10.6-x86_64-3.6/mymodmodule.c:550:19: error: use of undeclared identifier 'n1'
vector_Dims[0]=(n1);
^
/var/folders/r_/b16rpth9643dx5csqdw29wn40000gn/T/tmpm_sqc9ce/src.macosx-10.6-x86_64-3.6/mymodmodule.c:614:32: warning: incompatible function pointer types
assigning to 'f2py_init_func' (aka 'void (*)(int *, long *, void (*)(char *, long *), int *)') from 'void (*)(int *, int *, void (*)(char *, int *), int
*)' [-Wincompatible-function-pointer-types]
f2py_vars_def[i_f2py++].func = b;
^ ~
2 warnings and 1 error generated.
编辑2:
一种选择可能是创建一个包装器,例如这样的包装器(wrapper.f90
:
module wrapper
implicit none
contains
SUBROUTINE wrap_add_vector2(vector,n1in)
USE vars, ONLY: b, n2
IMPLICIT NONE
integer, INTENT(IN) :: n1in
doubleprecision, INTENT(in) :: vector(n1in)
INTEGER :: i, j
DO i = 1, n1in
DO j = 1, n2
b(i,j) = b(i,j) + vector(i)
ENDDO
ENDDO
END SUBROUTINE wrap_add_vector2
end module wrapper
但是,使用f2py -m wrapper -c mymod.f90 wrapper.f90
进行编译仍然会导致相同的问题,即f2py
无法编译mymod.f90
。整个内容应该可以作为numpy
扩展名使用。