在python3.7+vs2019环境下使用f2py将fortran和c++程序编译为python库

前言

今天务必开贴记录下将Fortran或c++程序编译为python库的方法。
起因是老师给了一个Fortran函数,无奈本人看不懂,因而想办法将其编译成python库调用。

步骤

1安装Fortran和Visual Studio编译环境

我之前用的是VS2019,所以安装了Intel Parallel Studio XE 2019(Fortran)。
附Fortran下载连接:
链接:https://pan.baidu.com/s/1ESqKiF4f3E00CyRFPMWOpg
提取码:7wp4
顺便说一下,vs2019去官网下载社区版,注册个邮箱就行,不用破解。

2配置vs在python中的路径

把C:\Program Files\Python\Lib\distutils_msvccompiler.py复制到桌面,我使用python的发行版Anaconda,所以路径是C:\ProgramData\Anaconda3\Lib\distutils,在函数_find_vc2017中直接指定VS2019路径,添加path = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise"即可,修改后的内容为:

def _find_vc2017():
    """Returns "15, path" based on the result of invoking vswhere.exe
    If no install is found, returns "None, None"

    The version is returned to avoid unnecessarily changing the function
    result. It may be ignored when the path is not None.

    If vswhere.exe is not available, by definition, VS 2017 is not
    installed.
    """
    import json

    root = os.environ.get("ProgramFiles(x86)") or os.environ.get("ProgramFiles")
    if not root:
        return None, None

    try:
        path = subprocess.check_output([
            os.path.join(root, "Microsoft Visual Studio", "Installer", "vswhere.exe"),
            "-latest",
            "-prerelease",
            "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
            "-property", "installationPath",
        ], encoding="mbcs", errors="strict").strip()
    except (subprocess.CalledProcessError, OSError, UnicodeDecodeError):
        return None, None
        
    path = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise"  #txf add
    path = os.path.join(path, "VC", "Auxiliary", "Build")
    if os.path.isdir(path):
        return 15, path

    return None, None

为防止出错可以直接复制替换。
把修改后的_msvccompiler.py文件复制到C:\Program Files\Python\Lib\distutils目录下。
如果掠过这步,编译时将报错:

error: Unable to find vcvarsall.bat

3测试c++编译环境

创建两个文件,一个源文件,一个签名文件
文件1:

/* File foo.c */
void foo(int n, double *x, double *y) {
  int i;
  for (i=0;i<n;i++) {
    y[i] = x[i] + i;
  }
}

文件2:

! File m.pyf
python module m
interface
  subroutine foo(n,x,y)
    intent(c) foo                 ! foo is a C function
    intent(c)                     ! all foo arguments are 
                                  ! considered as C based
    integer intent(hide), depend(x) :: n=len(x)  ! n is the length
                                                 ! of input array x
    double precision intent(in) :: x(n)          ! x is input array 
                                                 ! (or  arbitrary sequence)
    double precision intent(out) :: y(n)         ! y is output array, 
                                                 ! see code in foo.c
  end subroutine foo
end interface
end python module m

创建文件后,在命令行中输入

cd <上文文件所在目录>
f2py m.pyf foo.c -c #编译

之后在当前目录下得到 m.cp37-win_amd64.pyd 文件
在python下测试的结果
测试成功!!!
查看模块文档
在这里插入图片描述

4测试Fortran编译环境

废话少说, 先建立一个testfortran.f90的文件如下:

!SUBROUTINE      
      SUBROUTINE ADDSUB(A,B,C,D)
      IMPLICIT NONE
      DOUBLE PRECISION A,B,C,D
!f2py intent(in) :: A,B
!f2py intent(out) :: C,D
      C = A + B
      D = A - B
      print*, "ADDSUB From Fortran!"
      print*, "ADD=",C
      print*, "SUB=",D
      RETURN
      END

注意这两行的代码:

!f2py intent(in) :: A,B
!f2py intent(out) :: C,D

对于Fortran只是注释,但对于f2py却很重要,相当于"签名".

注意签名的注释前面不能有空格!

当然也可以写成如下的形式:

Cf2py intent(in) :: A,B
Cf2py intent(out) :: C,D

下面开始编译Fortran代码为python模块,打开CMD窗口,输入如下命令:

f2py -m testfortran -c testfortran.f90

会在当前目录下生成testfortran.cp37-win_amd64.pyd文件和一个文件夹,将该文件夹中的dll文件copy到testfortran.cp37-win_amd64.pyd文件同级目录下,使用方法同上。

参考链接

  1. https://www.jianshu.com/p/d432568133e4
  2. https://blog.csdn.net/rumswell/article/details/7377438
  3. https://blog.csdn.net/rumswell/article/details/7377339
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值