Calling a Matlab function in Fortran

17 views (last 30 days)
Imli Wiese
Imli Wiese on 2 Feb 2022
Edited: James Tursa on 2 Feb 2022
Using the MATLAB Engine API for Fortran, I am trying to call a simple Matlab function from a Fortran code.
I followed the fengdemo example found here : https://fr.mathworks.com/help/matlab/matlab_external/build-and-run-fortran-engine-applications-on-linux.html . It worked, so I want to adapt my Fortran code to call a specific Matlab script I wrote.
My Matlab script call_fortran.m is very simple: it takes x as an entry and multiplies it by 2:
function multiply = call_fortran(x)
multiply = 2*x;
end
I want my Fortran code to generate a variable my_x, open a Matlab session, send the variable to the workspace, apply the function call_fortran and display the result. Using the fengdemo.f code, I wrote :
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
C nlhs = 1
C plhs = 1
C nrhs = 1
C prhs = 1
C integer*4 mexCallMATLAB(nlhs, plhs, nrhs, prhs, functionName)
So I have my my_x, I send it to Matlab, but how do I apply the call_fortran.m function and get the new value of my_x ? Thank you in advance for your help!

Answers (1)

James Tursa
James Tursa on 2 Feb 2022
Edited: James Tursa on 2 Feb 2022
You have two fundamental errors with this code. You do not use the correct variable type for my_x, and you cannot call mexCallMATLAB( ) from an Engine application (that can only be used in mex routines). Let's fix these.
First, the my_x variable needs to be an mxArray, not a double precision variable. There are various ways to do this, but for a scalar, the easiest way to create this array is as follows:
mwPointer, external :: mxCreateDoubleScalar
mwPointer my_x
my_x = mxCreateDoubleScalar(6.d0)
Then you can pass this to the MATLAB Engine per your current code. To call your function in the MATLAB Engine workspace, you need to evaluate a string there:
integer*4, external :: engEvalString
integer*4 status
status = engEvalString( ep, 'result = call_fortran(my_x)' )
The result should display in the Engine workspace since we did not terminate the string with a semi-colon. If you want to get the result back into your Fortran code, you would need to do something like this:
mwPointer, external :: engGetVariable
mwPointer result
result = engGetVariable( ep, 'result' )
The result inside your Fortran code will be an mxArray. To extract the number there are various ways, but for a scalar it would be easiest to just do as follows (the real*8 is used instead of double precision to match the MATLAB API signature in the doc exactly):
real*8, external :: mxGetScalar
real*8 myresult
myresult = mxGetScalar(result)
To avoid memory leaks, once you are done with the mxArray variables you should destroy them. E.g.,
call mxDestroyArray(my_x)
call mxDestroyArray(result)
Having written all this, are you sure you want to create MATLAB Engine applications, and not mex routines? Mex routines are generally easier to work with and don't involve extra data copies to pass variables back & forth.

Tags

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!