Memory management 使用ctypes在Python中包装Fortran模块

Memory management 使用ctypes在Python中包装Fortran模块,memory-management,fortran,ctypes,f2py,fortran-iso-c-binding,Memory Management,Fortran,Ctypes,F2py,Fortran Iso C Binding,我正在尝试使用ctypes库包装一些要从Python调用的Fortran模块。我将直接从Fortran转换到Python,而不编写任何C代码。只需编译一个共享库 然而,我正在努力寻找内存分配的最佳方法,即谁应该拥有数据。我应该在Fortran模块内部进行分配,然后使用ctypes公开数据,还是应该使用numpy进行分配,并将其作为参数传递给Fortran 我也愿意做中间步骤并编写C包装(F->C->Python)。但同样的问题也出现了。 谢谢 PS:我知道F2Py存在,我知道如何使用它,但我对使

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


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

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

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

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_,lx_,ly_) bind(c)
        integer(c_int),intent(in),value :: lx_,ly_
        real(c_double),intent(in) :: phi_(lx_,ly_)
        call init_fields(phi_,lx_,ly_)
    end subroutine

    subroutine wrap_get_phi(phi_,lx_,ly_) bind(c)
        integer(c_int),intent(in),value :: lx_,ly_
        real(c_double),intent(inout) :: phi_(lx_,ly_)
        phi_ = phi(1:lx,1:ly)
    end subroutine
end module
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,c_int]
    angio.wrap_init_fields(phi,Nx,Ny)
    return

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

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

请注意,“最好的”可能是基于意见的。最好显示一些代码,说明实际如何使用数据。通常,全局数据是一件坏事。模块数据在某种意义上也是全局性的。@VladimirF添加了一些代码:)我的意思是性能和安全方面的最佳,我在这里看不到任何性能或安全问题。这是一个真正的设计选择。全局数据通常是反模式的。关于性能——您拥有代码,您必须衡量性能。“使用numpy分配并将其作为参数传递给Fortran”可能比“在Fortran内部分配并将分配传递给Python”更简单、更简洁。也就是说,Fortran 2018增加了C和Fortran之间Fortran分配的互操作性,一些编译器已经实现了它,比如
ifort