python调用fortran的3种形式【f2py,动态链接库,os命令】

一、f2py调用fortran

基于 F2PY,在 Python 中调用 Fortran 函数的基本流程是:

  • Fortran 代码
  • 使用f2py编译 Fortran 代码,产生动态库
  • 在 Python 中通过import引入动态库

注意: F2py 支持有限的 Fortran 子集。

"""======================1.fortran程序========================="""
function foo(a) result(b)
    !kind说明精度
    implicit none
    real(kind=8), intent(in)    :: a(:,:)
    complex(kind=8)             :: b(size(a,1),size(a,2))
    b = exp((0,1)*a)
end function foo

"""=============2.编译fortran程序,生成动态链接库==============="""
f2py -c -m myflib testfun.f90 
#myflib为包名,testfun.f90为上面fortran代码
#在cmd输入上面的命令

"""===================3.import引入动态链接库===================="""
import myflib
import numpy as np
a = np.array([[1,2,3,4], [5,6,7,8]], order='F')
print(myflib.foo(a))

在这里插入图片描述

二、使用动态链接库

Fortran 2003 标准引入了 iso_c_bindings 作为提高与 C 互操作性的一种手段。
在 Python 方面,ctypes 是 stdlib 的一部分,它实现了与外部函数的接口。
这两个工具可以结合起来创建一个支持 Fortran 和 Python 兼容性的接口。
注意:
ctypes不支持复数,可以包装依赖其他函数。
处理多维数组:c和fortran函数返回类型不能是数组。
这是Python 中使用 Fortran 的最通用方式。

2.1 fortran程序:定义了两个函数

1.sum2函数实现双精度浮点数并添加数字 2。
2.double_array函数实现多维数组运算
3.保存为ctypes_test.f90

!bind() 方法创建一个新的函数,在 bind() 被调用时,
!这个新函数的 this 被指定为 bind() 的第一个参数,
!而其余参数将作为新函数的参数,供调用时使用。
function sum2(a) result(b) bind(c, name='sum2')
    use iso_c_binding !fortran自带的
    implicit none
    real(c_double), intent(in)  :: a
    real(c_double)              :: b
    b = a + 2.d0
end function sum2

! 多维数组函数
subroutine double_array(x,N) bind(C, name="double_array")
    use iso_c_binding
    implicit none
    integer(c_int), intent(in), value   :: N
    real(c_double), intent(inout)       :: x(N,N)
    x  = exp(x)
end subroutine double_array

2.2 生成动态链接库

在cmd输入下面的命令

gfortran -shared ctypes_test.f90 -o myflib_ctype.so

2.3 python调用fortran

1.导入动态链接库
2.明确输入输出类型
3.传值调用fortran

import ctypes as ct
import numpy as np # 为处理fortran的多维数组
"=======================调用sum2()========================="
# 1.导入动态链接库,最好写绝对路径
fortlib = ct.CDLL('C:/fortranDM/myflib_ctype.so') 
# 2.导出fortran函数
f = fortlib.sum2
# 3.指定输入输出类型
# ct.POINTER 类似指针
f.argtypes = [ct.POINTER(ct.c_double)]
f.restype = ct.c_double
# 4.创建double对象并将其传递给Fotran(通过引用)
a = ct.c_double(5)
b = f(ct.byref(a))
print(str(f.__name__)+"函数输出:\n",b)

"=======================调用double_array()========================="
# 1.导出fortran函数
f = fortlib.double_array
# 2.指定输入类型
f.argtypes=[ct.POINTER(ct.c_double), ct.c_int]
# 3.创建一个double数组
x = np.ones((3,3), order="F")
x_ptr = x.ctypes.data_as(ct.POINTER(ct.c_double))
# 4.创建double对象并将其传递给Fotran(通过引用)
rint = f(x_ptr, ct.c_int(3))
print(str(f.__name__)+"函数输出:\n",x)

在这里插入图片描述
参考文献:https://www.matecdev.com/posts/fortran-in-python.html

三、利用python的os包调用fortran

下面是fortran程序,分别求半径R=1,3,12.5时的圆周长。
此源程序由二部分组成:主程序和子程序。

!主程序
real :: r(3)
data r /1, 3, 12.5/
do i=1,3
	print *, '半径=', r(i), '圆周长=', C(r(i))
end do
end
!次程序
function c(radius)
	pi=acos(-1.0)
	c=2*pi*radius
	return
end

3.1 os.system命令

os.system(“cmd”) 调用外部命令,程序只能返回命令运行返回码:0正常,1异常;但无法捕获cmd进程执行结果。

import os
os.system(r"gfortran  C:/fortranDM/test.f90")
# 只能输出0

优点:使用简单,可以执行一句话cmd行。
缺点:无法获取cmd执行结果,不能进行交互式调用,以及复杂调用操作。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值