Ubuntu 24.04 上实现 Python 调用 Fortran

在python中,调用fortran封装的函数。

目前我使用miniconda创建了py39的环境。
在 Ubuntu 24.04 上实现 Python 调用 Fortran 函数的工作流(Python -> Cython -> C -> Fortran)涉及配置多个工具和库。
通过这种方式,你实现了从 Python 调用 Fortran 的工作流。这个工作流的关键步骤是:

  1. 用 Fortran 编写函数。
  2. 用 C 编写 Fortran 函数的封装器。
  3. 用 Cython 调用 C 函数,并生成 Python模块。
  4. 用 Python 直接调用 Cython 模块。

环境安装

1 安装Fortran和C编译器

确保已经安装了Fortran编译器(如 gfortran)、C编译器(如 gcc)和Python环境管理工具(如 Miniconda)。

sudo apt install gfortran gcc make

2 安装Cython

在py39 Conda 环境中,安装 Cython:

conda activate py39
conda install cython

代码分析

文件夹组成:
project_directory/

├── fortran/
│ └── example.f90 # Fortran 源代码
├── c/
│ └── wrapper.c # C 源代码
├── cython/
│ └── cython_wrapper.pyx # Cython 源代码
├── python/
│ └── test.py # Python 测试代码
├── build/ # 编译生成的文件放置目录
│ └── (wrapper.o, example.o, .so 文件等)
├── makefile # 一键完成整个编译和测试流程
├── setup.py # 编译和打包配置
└── README.md # 软件包说明文件

Fortran代码

! example.f90
subroutine add_numbers(a, b, result) bind(C, name="add_numbers")
    implicit none
    double precision, intent(in) :: a, b
    double precision, intent(out) :: result
    result = a + b
end subroutine add_numbers

C代码

// wrapper.c
#include <stdio.h>

extern void add_numbers(double* a, double* b, double* result);

void c_add_numbers(double a, double b, double* result) {
    add_numbers(&a, &b, result);
}

Cython代码

# cython_wrapper.pyx
cdef extern void c_add_numbers(double a, double b, double* result)

def add_numbers(double a, double b):
    cdef double result
    c_add_numbers(a, b, &result)
    return result

Python代码

import sys
import os

# 动态获取项目根目录
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# 添加 build 目录到模块搜索路径
sys.path.append(os.path.join(project_root, 'build'))

from cython_wrapper import add_numbers

result = add_numbers(2.5, 3.7)
print(f"The result is: {result}")

setup代码

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
import os

# 设置环境变量,使用 gfortran 作为链接器
os.environ["LDSHARED"] = "gfortran -shared"

extensions = [
    Extension(
        name="cython_wrapper",
        sources=["cython/cython_wrapper.pyx"],
        extra_objects=["build/wrapper.o", "build/example.o"],  # 放入 build 目录
        libraries=["gfortran"],  # 链接 Fortran 库
        library_dirs=['/usr/lib/gcc/aarch64-linux-gnu/13'],  # Fortran 运行时库的位置
    )
]

setup(
    ext_modules=cythonize(extensions, compiler_directives={'language_level': "3"}),
    script_args=["build_ext", "--build-lib", "build"],  # 指定编译输出目录为 build
)

makefile代码

# Makefile

# 设置变量
FORTRAN_SRC = fortran/example.f90
C_SRC = c/wrapper.c
CYTHON_SRC = cython/cython_wrapper.pyx
BUILD_DIR = build
PYTHON_TEST = python/test.py
SO_FILE = $(BUILD_DIR)/cython_wrapper*.so

# 设置编译器和编译选项
GFORTRAN = gfortran
GCC = gcc
PYTHON = python
CYTHON = cython
SETUP = python setup.py build_ext --build-lib $(BUILD_DIR)

# 默认执行所有编译和测试
all: build_dir fortran c cython run_test

# 创建 build 目录
build_dir:
	mkdir -p $(BUILD_DIR)

# 编译 Fortran 文件
fortran: build_dir
	$(GFORTRAN) -c $(FORTRAN_SRC) -o $(BUILD_DIR)/example.o

# 编译 C 文件
c: build_dir
	$(GCC) -c $(C_SRC) -o $(BUILD_DIR)/wrapper.o

# 编译 Cython 文件,生成 .so 文件
cython: build_dir fortran c
	$(SETUP)

# 运行 Python 测试
run_test: $(SO_FILE)
	$(PYTHON) $(PYTHON_TEST)

# 清理生成的文件
clean:
	rm -rf $(BUILD_DIR)/*.o $(BUILD_DIR)/*.so

.PHONY: all build_dir fortran c cython run_test clean

编译和运行步骤

1. 编译 Fortran 文件

进入项目的根目录,并编译 Fortran 文件:

gfortran -c fortran/example.f90 -o fortran/example.o

2. 编译 C 文件

继续编译 C 文件:

gcc -c c/wrapper.c -o c/wrapper.o

3. 编译 Cython 模块

使用 setup.py 文件来编译 Cython 模块:

python setup.py build_ext --inplace

4. 运行 Python 测试

一切编译成功后,运行 Python 文件来测试调用:

python python/test.py

你应该看到输出:

The result is: 6.2
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值