Ubuntu中Fortran与MATLAB协同工作的实现方法
在Ubuntu系统中,Fortran与MATLAB可通过共享库调用(MATLAB调用Fortran编译的.so文件)或MEX文件(Fortran通过MEX接口集成到MATLAB)两种主要方式协同工作,以下是具体步骤及注意事项:
gfortran是开源且兼容性好的选择,通过以下命令安装:sudo apt update && sudo apt install gfortran
matlab命令可在终端中运行。gfortran,无需额外配置;若使用Intel Fortran Compiler,需通过mex -setup fortran命令让MATLAB识别编译器。创建Fortran源文件(如my_fortran_lib.f90),编写需要调用的子程序。注意:
intent属性明确参数方向(in/out/inout);print *),如需调试可使用open()写入文件。subroutine add_numbers(a, b, c)
real(8), intent(in) :: a, b ! 输入参数
real(8), intent(out) :: c ! 输出参数
c = a + b ! 简单加法运算
end subroutine add_numbers
使用gfortran编译为.so文件(Linux下的动态链接库),需添加-shared(生成共享库)、-fPIC(位置无关代码,动态链接必需)选项:
gfortran -shared -fPIC -o libmy_fortran_lib.so my_fortran_lib.f90
编译成功后,会在当前目录生成libmy_fortran_lib.so文件。
MATLAB通过calllib函数调用共享库中的子程序,步骤如下:
loadlibrary加载.so文件及对应的头文件(需手动创建头文件);real(8)对应MATLAB的double);calllib指定库名、子程序名及参数;unloadlibrary释放资源。示例MATLAB代码:
% 定义Fortran子程序的头文件内容(需保存为my_fortran_lib.h)
% void add_numbers(double *a, double *b, double *c);
% 加载共享库及头文件
if libisloaded('my_fortran_lib')
unloadlibrary('my_fortran_lib');
end
loadlibrary('libmy_fortran_lib.so', 'my_fortran_lib.h');
% 准备输入参数
a = 3.5; b = 2.5;
c = 0; % 输出变量需初始化
% 调用Fortran子程序
calllib('my_fortran_lib', 'add_numbers', a, b, c);
% 显示结果
disp(['计算结果: ', num2str(c)]);
% 卸载共享库
unloadlibrary('my_fortran_lib');
my_fortran_lib.h),内容为子程序的C风格声明(void add_numbers(double *a, double *b, double *c););real(8)对应MATLAB的double,integer对应MATLAB的int32/int64;LD_LIBRARY_PATH环境变量(如export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/library),避免MATLAB找不到库文件。MEX文件(MATLAB Executable)是MATLAB可调用的动态链接库,允许Fortran代码直接在MATLAB中运行。适用于需要复用现有Fortran代码或与MATLAB深度交互的场景。
MEX文件需包含mexFunction入口点(类似C的main函数),并通过MATLAB API实现数据传递。示例代码(my_fortran_mex.f90):
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
use mex
implicit none
integer, intent(in) :: nlhs, nrhs ! 输出/输入参数数量
type(mxArray), intent(out) :: plhs(nlhs) ! 输出参数
type(mxArray), intent(in) :: prhs(nrhs) ! 输入参数
real(8) :: a, b, c ! Fortran变量
mwPointer :: mx_a, mx_b, mx_c ! mxArray指针
! 检查输入输出数量
if (nrhs /= 2) then
call mexErrMsgIdAndTxt('MATLAB:fortran_mex:invalidInput', '需2个输入参数');
elseif (nlhs > 1) then
call mexErrMsgIdAndTxt('MATLAB:fortran_mex:invalidOutput', '最多1个输出参数');
end if
! 从输入参数获取数据(mxArray转Fortran变量)
mx_a = prhs(1); a = mxGetScalar(mx_a);
mx_b = prhs(2); b = mxGetScalar(mx_b);
! 调用Fortran计算子程序
call add_numbers(a, b, c)
! 创建输出mxArray并赋值
plhs(1) = mxCreateDoubleScalar(c)
end subroutine mexFunction
subroutine add_numbers(a, b, c)
real(8), intent(in) :: a, b
real(8), intent(out) :: c
c = a + b
end subroutine add_numbers
在MATLAB中编译Fortran MEX文件,需确保mex能识别Fortran编译器(通过mex -setup fortran配置):
mex -v my_fortran_mex.f90
编译成功后,会在当前目录生成my_fortran_mex.mexa64文件(Ubuntu下的MEX文件扩展名)。
MEX文件可直接像MATLAB内置函数一样调用:
a = 3.5; b = 2.5;
result = my_fortran_mex(a, b); % 调用Fortran MEX文件
disp(['计算结果: ', num2str(result)]);
mexFunction的参数顺序固定(nlhs、plhs、nrhs、prhs),需严格遵循;mxArray是MATLAB的内存对象,需通过mxCreate*创建、mxDestroyArray释放,避免内存泄漏;mxGetScalar(获取标量)、mxGetPr(获取数组指针)等API函数实现Fortran与MATLAB数据转换。LD_LIBRARY_PATH是否包含共享库路径,或使用addpath将路径添加到MATLAB搜索路径;real(8)与MATLAB的double对应,数组维度需一致;mex -setup fortran已正确配置Fortran编译器,且Fortran代码符合MEX接口规范。通过上述方法,可在Ubuntu系统中实现Fortran与MATLAB的高效协同,结合Fortran的高性能计算与MATLAB的便捷数据处理、可视化功能,满足科学计算与工程应用的需求。