温馨提示×

Ubuntu下Fortran与MATLAB如何协同工作

小樊
37
2025-11-16 18:11:19
栏目: 编程语言

Ubuntu下Fortran与MATLAB协同工作

一、常用协同方式概览

  • MATLAB 调用 Fortran:将计算密集的例程编译为 MEX,在 MATLAB 中像内置函数一样调用;或在 Fortran 中调用 MATLAB 引擎 启动会话、传参与执行命令。
  • Fortran 调用 MATLAB:在 Fortran 程序里启动 MATLAB 引擎,把数据传入、执行 MATLAB 函数、取回结果。
  • 数据文件交换:用 .mat(v7.3 为 HDF5)或文本/二进制在两者之间传递数据。
  • 官方文档将接口归纳为:Fortran MEX APIMATLAB Fortran 引擎 APIFortran 矩阵 API、以及读写 MAT 文件四类,覆盖上述全部场景。

二、MATLAB 调用 Fortran

  • 方案A MEX(推荐):编写 Fortran 子程序,遵循 MEX 入口 mexFunction,用 mexCallMATLAB/mexEvalString 与 MATLAB 交互,用 mexGet/mexPut** 在 MEX 与 MATLAB 工作区之间传递数据;在 MATLAB 中先执行 mex -setup FORTRAN 配置编译器,再用 mex your_fortran_file.f90 生成 MEX 并调用。
  • 方案B 引擎(适合需要完整 MATLAB 环境的任务):在 Fortran 中调用 MATLAB 引擎 API 启动会话、传递数组、执行命令、取回结果;适合调用大量 MATLAB 内置函数或绘图。
  • 方案C 动态库(Windows 为主):将 Fortran 编译为 DLL,在 MATLAB 用 loadlibrary/calllib/unloadlibrary 调用;Linux 下对应为 .so,可用 loadlibrary 调用共享库(需符合平台 ABI 与编译器约定)。
  • 要点:MEX 性能最佳、集成度最高;引擎最灵活;DLL/SO 适合已有库复用。

三、Fortran 调用 MATLAB

  • 使用 MATLAB Fortran 引擎 API:在 Fortran 程序中启动 MATLAB 引擎会话,通过 API 将 Fortran 数组传入 MATLAB、调用 MATLAB 函数(如数值计算、优化、绘图)、再把结果取回;适合以 Fortran 为主程序、借助 MATLAB 做计算与可视化的场景。
  • 要点:需正确初始化引擎、管理会话与内存,并按 API 规范进行数据拷贝与类型匹配。

四、数据文件交换与格式选择

  • .mat v7.3+(HDF5):用 HDF5 库在 Fortran 直接读写;Ubuntu 可安装 libhdf5-dev 获取头文件与库。
  • 旧版 .mat(v7 及以下):可用 MATIO(C 库)配合 Fortran 的 C 接口读写,或让 MATLAB 导出为文本/CSV/HDF5 再读取。
  • 文本/CSV:最简单通用,Fortran 直接按列/行读取;注意分隔符、表头、缺失值与数值格式。
  • 二进制:高效但需双方约定字节序、数据类型、维度顺序与存储布局(Fortran 列主序 vs MATLAB 列主序一致),便于零拷贝或最小拷贝传递。
  • 选型建议:跨平台与可移植优先 HDF5;快速调试用 文本/CSV;已有生态或历史数据用 MATIO

五、Ubuntu快速上手示例

  • 示例A 用 MEX 在 MATLAB 中调用 Fortran(Ubuntu)
    1. 安装工具链与依赖:sudo apt-get install gfortran libhdf5-dev;确保 MATLAB 已安装并配置好编译器(在 MATLAB:mex -setup FORTRAN)。
    2. 编写 Fortran 源文件(示例 addvec.f90):
      subroutine mexFunction(nlhs, plhs, nrhs, prhs)
        use, intrinsic :: iso_c_binding, only: c_ptr, c_loc
        implicit none
        integer, intent(in) :: nlhs, nrhs
        type(c_ptr), intent(in) :: prhs(*)
        type(c_ptr), intent(out) :: plhs(*)
        ! 简化示例:C = A + B(均为列向量)
        real(8), pointer :: A(:), B(:), C(:)
        integer :: m, n
      
        ! 获取输入 mxArray 并转为 Fortran 指针(实际项目应使用 mxGetPr/mxGetDimensions 等)
        ! 这里省略错误检查与维度校验,生产代码需完善
        call mxCopyPtrToReal8(mxGetPr(prhs(1)), A, size(A))
        call mxCopyPtrToReal8(mxGetPr(prhs(2)), B, size(B))
      
        m = size(A); n = size(B)
        if (m /= n) call mexErrMsgIdAndTxt('MATLAB:addvec:dimMismatch','A and B must match')
        allocate(C(m))
        C = A + B
      
        ! 创建输出 mxArray 并拷贝数据(示意)
        plhs(1) = mxCreateDoubleMatrix(m, 1, 0)
        call mxCopyReal8ToPtr(C, mxGetPr(plhs(1)), m)
        deallocate(C)
      end subroutine mexFunction
      
    3. 在 MATLAB 编译与调用:
      mex -v addvec.f90
      A = randn(5,1); B = randn(5,1);
      C = addvec(A,B);
      
  • 示例B 用 HDF5 在 Fortran 读取 MATLAB v7.3 的 .mat
    1. 安装 HDF5:sudo apt-get install libhdf5-dev
    2. 读取变量(示例 read_matlab_hdf5.f90):
      program read_mat
        use hdf5
        implicit none
        integer(hid_t) :: file_id, dset_id, memspace, filespace
        integer(hsize_t) :: dims(2) = [100, 100]
        real, allocatable :: data(:, :)
        integer :: err
      
        call h5open_f(err)
        call h5fopen_f('data.mat', H5F_ACC_RDONLY_F, file_id, err)
        call h5dopen_f(file_id, '/your_variable_name', dset_id, err)  ! 替换为实际变量名
        call h5dread_f(dset_id, H5T_NATIVE_DOUBLE, data, dims, err)
        call h5dclose_f(dset_id, err)
        call h5fclose_f(file_id, err)
        call h5close_f(err)
      
        print *, 'data(1,1)=', data(1,1)
      end program read_mat
      
    3. 编译与运行:
      gfortran -o read_mat read_matlab_hdf5.f90 -lhdf5 -I/usr/include/hdf5/fortran
      ./read_mat
      
  • 提示:MEX 示例省略了 mxArray 的创建、类型/维度检查与错误处理的完整流程,生产代码应结合 Fortran MEX API 文档完善;HDF5 示例需确保 .mat 文件变量名、维度与实际一致。

0