我在 f2py
中遇到了可分配数组的问题 . 在下面的代码中(存储在 mymod.f90
中),我创建了两个模块, vars
和 worker
:
-
vars
存储并分配数组b
-
worker
包含从vars
处理此数组的子例程 .
第一个 worker
-subroutine为 b
添加了一个标量 . 这按预期工作 . 问题在于下一个例程应该向数组 b
添加匹配第一维的向量 . 已实现的子例程 add_vector2
有效,但需要传递输入 vector
的维度 .
我需要的是一个只有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
?
Edit 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.
Edit 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
扩展名 .