使用 ctypes 在 Python 中包装 Fortran 模块

问题描述

我正在尝试使用 ctypes 库包装一些要从 Python 调用的 Fortran 模块。我直接从 Fortran 转到 Python,无需编写任何 C 代码。只需编译一个共享库。

然而,我正在为内存分配的最佳方法而苦苦挣扎,即谁应该拥有数据。我应该在 Fortran 模块内部分配,然后使用 ctypes 公开数据,还是应该使用 numpy 分配并作为参数传递给 Fortran。

我也愿意做中间步骤并编写 C 包装器 (F->C->Python)。但是同样的问题出现了。 谢谢!

PS:我知道 F2Py 存在我知道如何使用它,但我有兴趣采用 ctypes 方式。

mod.f90:

module angio_global

    use iso_c_binding

    implicit none

    integer  :: lx,ly
    real*8 :: raio_init

    real*8,allocatable :: phi(:,:)
    real*8 :: epsilon,rho_phi


contains

    subroutine init_fields(phi_,lx_,ly_)
        integer,intent(in) :: lx_,ly_
        real*8,intent(in) :: phi_(lx_,ly_)
        integer :: i,j
        real*8 :: dx,dy
        lx = lx_
        ly = ly_
        allocate(phi(0:lx+1,0:ly+1))
        phi(1:lx,1:ly) = phi_
        raio_init = 20.0_dp
        epsilon = 1.0_dp
        rho_phi = 1.0_dp
        do j=1,ly
            do i=1,lx
                dx = i-lx/2.0_dp
                dy = j-ly/2.0_dp
                if(dx**2+dy**2<raio_init**2) phi(i,j) = 1.0_dp
            enddo
        enddo
    end subroutine

    subroutine wrap_init_fields(phi_,ly_) bind(c)
        integer(c_int),intent(in),value :: lx_,ly_
        real(c_double),ly_)
        call init_fields(phi_,ly_)
    end subroutine

    subroutine wrap_get_phi(phi_,intent(inout) :: phi_(lx_,ly_)
        phi_ = phi(1:lx,1:ly)
    end subroutine
end module

caller.py:

from ctypes import CDLL,c_int,c_double,c_float
import numpy as np
from numpy.ctypeslib import ndpointer
import matplotlib.pyplot as plt
angio = CDLL('./global.so')

def init_fields(phi):
    Nx,Ny = np.shape(phi)
    phi_ptr = ndpointer(dtype=phi.dtype,shape=phi.shape,flags="F_CONTIGUOUS")
    angio.wrap_init_fields.argtypes = [phi_ptr,c_int]
    angio.wrap_init_fields(phi,Nx,Ny)
    return

def get_phi(phi):
    Nx,flags="F_CONTIGUOUS")
    angio.wrap_get_phi.argtypes = [phi_ptr,c_int]
    angio.wrap_get_phi(phi,Ny)

phi = np.zeros((200,200),dtype = np.float64,order="F")-1.0
init_fields(phi)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)