我在 f2py 中遇到了可分配数组的问题 . 在下面的代码中(存储在 mymod.f90 中),我创建了两个模块, varsworker

  • 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 扩展名 .