Memory management 使用ctypes在Python中包装Fortran模块
我正在尝试使用ctypes库包装一些要从Python调用的Fortran模块。我将直接从Fortran转换到Python,而不编写任何C代码。只需编译一个共享库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存在,我知道如何使用它,但我对使
然而,我正在努力寻找内存分配的最佳方法,即谁应该拥有数据。我应该在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
。