如何通过MEX在MATLAB中无拷贝访问Fortran变量?
在Fortran MEX函数中无拷贝只读访问MATLAB多维数组
核心思路
MATLAB的数组内存采用列优先存储(和Fortran完全一致),因此可以直接获取其数据区的指针,通过Fortran的ISO_C_BINDING模块将C风格指针转换为Fortran可直接访问的数组指针,全程无需拷贝内存。
实现步骤与代码示例
1. 基础输入参数场景(MEX函数接收输入数组)
以下是一个完整的Fortran MEX函数示例,实现只读访问输入的二维双精度数组,计算所有元素的和:
#include "fintrf.h" subroutine mexFunction(nlhs, plhs, nrhs, prhs) use, intrinsic :: ISO_C_BINDING implicit none ! MEX接口标准参数 mwPointer :: plhs(*), prhs(*) integer :: nlhs, nrhs ! 局部变量 mwPointer :: mx_input, data_ptr integer :: array_dims(2) real(c_double), pointer :: matlab_array(:,:) real(c_double) :: total_sum ! 校验输入参数数量 if (nrhs /= 1) then call mexErrMsgIdAndTxt('MATLAB:NoCopyRead:BadInputCount', & '错误:仅需传入一个输入数组') end if ! 获取输入数组的mxArray指针 mx_input = prhs(1) ! 校验数组类型(仅支持实双精度数组) if (.not. mxIsDouble(mx_input) .or. mxIsComplex(mx_input)) then call mexErrMsgIdAndTxt('MATLAB:NoCopyRead:InvalidType', & '错误:输入必须是实双精度数组') end if ! 获取数组维度信息 call mxGetDimensions(mx_input, array_dims) ! 获取MATLAB数组数据区的指针(无拷贝) data_ptr = mxGetData(mx_input) ! 将C风格指针转换为Fortran可直接访问的数组指针 call c_f_pointer(c_loc(data_ptr), matlab_array, [array_dims(1), array_dims(2)]) ! 只读访问数组,执行计算 total_sum = 0.0d0 do j = 1, array_dims(2) do i = 1, array_dims(1) total_sum = total_sum + matlab_array(i,j) end do end do ! 创建输出结果 plhs(1) = mxCreateDoubleScalar(total_sum) end subroutine mexFunction
2. 访问MATLAB工作区变量场景
如果需要访问的是MATLAB工作区中的变量(而非MEX函数的输入参数),可以用mexGetVariablePtr获取指针,后续转换逻辑一致:
! 获取工作区中名为"my_array"的变量指针 data_ptr = mexGetVariablePtr('caller', 'my_array') ! 后续同样用c_f_pointer转换为Fortran数组指针
关键说明
- 内存安全:通过这种方式获取的指针指向MATLAB管理的内存,绝对不可修改数组内容,否则会破坏MATLAB的内存管理机制,导致崩溃或数据损坏。
- 维度匹配:MATLAB数组是列优先存储,与Fortran完全兼容,转换时直接使用
mxGetDimensions返回的维度即可,无需调整顺序。 - 复数数组处理:如果是复数数组,需分别用
mxGetData获取实部指针、mxGetImagData获取虚部指针,再分别转换为Fortran数组指针。 - 编译方式:使用MATLAB的
mex命令编译代码,例如:mex no_copy_read.f90(假设代码文件名为no_copy_read.f90)。
内容的提问来源于stack exchange,提问作者Vinicius Oliveira Fontes
相关产品推荐
相关产品推荐

