在 Fortran 中调用 Matlab 函数

Calling a Matlab function in Fortran

使用 MATLAB Engine API for Fortran,我试图从 Fortran 代码调用一个简单的 MATLAB 函数。

我按照找到的 fengdemo 示例进行了操作 here。 它有效,所以我想调整我的 Fortran 代码以调用我编写的特定 Matlab 脚本。

我的 MATLAB 脚本 call_fortran.m 非常简单:它将 x 作为一个条目并将其乘以 2:

function multiply = call_fortran(x)
     multiply = 2*x;
end

我希望我的 FORTRAN 代码生成变量 my_x,打开 MATLAB 会话,将变量发送到工作区,应用函数 call_fortran 并显示结果。使用 fengdemo.f 代码,我写道:

program main
C     Declarations
implicit none
mwPointer engOpen, engGetVariable, mxCreateDoubleMatrix
mwPointer mxGetPr
mwPointer ep, my_x  ! ep: variable linked to engOpen, starting a Matlab session, my_x: variable que je veux donner a Matlab
double precision my_x
integer engPutVariable, engEvalString, engClose
integer temp, status
mwSize i
my_x = 6
ep = engOpen('matlab ')
if (ep .eq. 0) then
    write(6,*) 'Can''t start MATLAB engine'
    stop
endif
    
C     Place the variable my_x into the MATLAB workspace
status = engPutVariable(ep, 'my_x', my_x)
C
if (status .ne. 0) then 
    write(6,*) 'engPutVariable failed'
    stop
endif
! My issue now is to call the correct Matlab script
! nlhs = 1
! plhs = 1
! nrhs = 1
! prhs = 1
! integer*4 mexCallMATLAB(nlhs, plhs, nrhs, prhs, functionName)

所以我有 my_x,我将它发送到 MATLAB,但是如何应用 call_fortran.m 函数并获得 my_x 的新值?

这段代码有两个基本错误。您没有为 my_x 使用正确的变量类型,并且您不能从引擎应用程序(只能在 mex 例程中使用)调用 mexCallMATLAB( )。让我们解决这些问题。 首先,my_x 变量需要是一个 mxArray,而不是双精度变量。有多种方法可以做到这一点,但对于标量,创建此数组的最简单方法如下:

mwPointer, external :: mxCreateDoubleScalar
mwPointer my_x
my_x = mxCreateDoubleScalar(6.d0)

然后您可以根据您当前的代码将其传递给 MATLAB 引擎。要在 MATLAB 引擎工作区中调用您的函数,您需要在那里计算一个字符串:

integer*4, external :: engEvalString
integer*4 status
status = engEvalString( ep, 'result = call_fortran(my_x)' )

结果应该显示在引擎工作区中,因为我们没有以 semi-colon 终止字符串。如果您想将结果返回到您的 Fortran 代码中,您需要执行如下操作:

mwPointer, external :: engGetVariable
mwPointer result
result = engGetVariable( ep, 'result' )

您的 Fortran 代码中的结果将是一个 mxArray。要提取数字,有多种方法,但对于标量,最简单的方法如下(使用 real*8 而不是双精度来精确匹配文档中的 MATLAB API 签名):

real*8, external :: mxGetScalar
real*8 myresult
myresult = mxGetScalar(result)

为避免内存泄漏,一旦您使用完 mxArray 变量,您应该销毁它们。例如,

call mxDestroyArray(my_x)
call mxDestroyArray(result)

写完所有这些,您确定要创建 MATLAB 引擎应用程序,而不是 mex 例程吗? Mex 例程通常更易于使用,并且不涉及额外的数据副本来来回传递变量。