Mex/Fortran passing data

Hello,
Is it possible to pass from matlab data labeled as follows and if so what would be the efficient way to do it?
AeroConfig_Hub_position %a (3*1) vector
AeroConfig_Hub_orientation %a (3*3) matrix
AeroConfig_Hub_translationvel %a (3*1)vector
AeroConfig_Hub_rotationvel %a (3*1) vector
through a mex interface that will format them to be read by the fortan code as:
Aeroconfig%Hub%position
Aeroconfig%Hub%orientation
AeroConfig%Hub%rotationvel
AeroConfig%Hub%translationvel
any help is greatly appreciated.

 채택된 답변

James Tursa
James Tursa 2012년 6월 26일

2 개 추천

Download this package from the FEX:
Follow the instructions to compile the modules. Then you can do stuff like this:
m-code:
myFortranMexRoutine(AeroConfig_Hub_position,...
AeroConfig_Hub_orientation,...
AeroConfig_Hub_translationvel,...
AeroConfig_Hub_rotationvel);
Fortran code:
#include "fintrf.h"
subroutine mexFunction(nlhs,plhs,nrhs,prhs)
use MatlabAPImx
implicit none
integer nlhs, nrhs
mwPointer plhs(*), prhs(*)
__yourtype__ Aeroconfig
AeroConfig%Hub%position = fpGetPr1(prhs(1))
AeroConfig%Hub%orientation = fpGetPr(prhs(2))
AeroConfig%Hub%translationvel = fpGetPr1(prhs(3))
AeroConfig%Hub%rotationvel = fpGetPr1(prhs(4))
Caution: The above is just an outline with no error checking. In production code you would need to check nrhs and nlhs to see if there are the correct number of inputs & outputs. And you would have to retrieve the data pointers via fpGetPr1 and fpGetPr into separate variables and examine if they are associated prior to using them. Etc.

댓글 수: 13

Chris
Chris 2012년 6월 26일
Hi James,
Thanks for the response. The package will help a lot. I get the following errors using it and wondered if you could tell me what is wrong.:
aerodyngateway.f90(32): error #6404: This name does not have a type, and must have an explicit type. [TURBINECOMPONENTS_HUB_POSITION]
TurbineComponents_Hub_position = fpGetPr1(plhs(1))
^
aerodyngateway.f90(32): error #6366: The shapes of the array expressions do not conform. [TURBINECOMPONENTS_HUB_POSITION]
TurbineComponents_Hub_position = fpGetPr1(plhs(1))
^
Declarations as follows:
TYPE :: Marker
REAL(8) :: Position(3)
REAL(8) :: Orientation(3,3)
REAL(8) :: TranslationVel(3)
REAL(8) :: RotationVel(3)
END TYPE Marker
TYPE :: AeroConfig
TYPE(Marker) :: Hub
END TYPE AeroConfig
Type(AeroConfig) :: TurbineComponents
James Tursa
James Tursa 2012년 6월 26일
You are using the MATLAB variable names with underscores on the Fortran side. Use the percent signs (%) as shown above and as shown in your original code to get at the structure components in Fortran. E.g.,
TurbineComponents%Hub%position = fpGetPr1(prhs(1))
TurbineComponents%Hub%orientation = fpGetPr(prhs(2))
TurbineComponents%Hub%translationvel = fpGetPr1(prhs(3))
TurbineComponents%Hub%rotationvel = fpGetPr1(prhs(4))
Chris
Chris 2012년 6월 26일
Thanks James. My mex file is now done correctly but I get the following link problems:
aerodyngateway.obj : error LNK2019: unresolved external symbol MATLABAPIMX_mp_FPGETPR1DOUBLE referenced in function MEXFUNCTION
aerodyngateway.obj : error LNK2019: unresolved external symbol MATLABAPIMX_mp_FPGETPR2DOUBLE referenced in function MEXFUNCTION
aerodyngateway.mexw64 : fatal error LNK1120: 3 unresolved externals
are these due to the modules not being compiled correctly?
Also am I correct in thinking that all I need to change the matlab compile programs to match it with my compiler/VS studio edition is the following :
options = [matlabroot '\bin\win32\mexopts\intelf91msvs2005engmatopts.bat']
James Tursa
James Tursa 2012년 6월 26일
You need to include the pre-compiled module object modules in the mex command line. E.g.,
% Do this once to get the module compiled
mex -c MatlabAPImx.f
% Then do this to compile your mex function
mex myFortranMexFunction.f MatlabAPImx.obj
James Tursa
James Tursa 2012년 6월 26일
Regarding the mex options, did you use mex -setup to select the compiler?
Chris
Chris 2012년 6월 26일
yes i selected the compiler using mex - setup. It works when I include the .obj. Thanks alot for the help.
A theoretical question: Is there a way to use the derived data types in fortran in a matlab code? So if say matlab calculated each component thats in type aeronconfig ( like hub, blade, tower) with each of those components having position, orientation, translationvel, rotationvel vectors then passed it via mex file to a function in fortran:
%Type(aeroconfig) :: turbinecomponents
%function(turbinecomponents).
So instead of passing each component individually, have it included in one large array that is passed once.
James Tursa
James Tursa 2012년 6월 26일
On the MATLAB side you can have a struct with the same component naming convention as on the Fortran side. E.g.,
TurbineComponents.Hub.Position = whatever;
TurbineComponents.Hub.Orientation = whatever;
:
etc.
Then you only have to pass in the one MATLAB struct variable. Inside the mex routine you can use mxGetField to pick off the desired components and then use the fpGetPr1 etc functions on the mxGetField results to get at the data and one-by-one copy them into their Fortran counterparts. There is no magic bullet to do the copying all in one fell swoop ... you have to write the component copying for each individual component since the actual storage of the data in memory is different on both sides.
James Tursa
James Tursa 2012년 6월 27일
Another alternative is to have your Fortran user defined data type contain pointers instead of arrays, and then just point them to the incoming MATLAB variable data. Works as long as you treat the input as read-only.
Chris
Chris 2012년 7월 2일
편집: Walter Roberson 2012년 7월 3일
Hi James,
I'm trying to follow your instructions with the struct command. I have TurbineComponents=struct('Hub',hub,'Tower',tower) with hub = struct('position',turbinecomponents.hub.position, 'orientation'...etc)
Is this the correct way for passing the array?
I also get the following errors when trying to compile my mex file and wanted to see if you knew what was wrong:
>> mex aerotest.f90 aerodyntest.obj
aerotest.f90(75): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: ( % [ . = =>
Two(TurbineComponents,A,B,C,D)
------------------------------------^
aerotest.f90(58): error #6303: The assignment operation or the binary expression operation is invalid for the data types of the two operands. [MXGETARRAY]
TurbineComponents = mxGetArray(turbine_ptr)
--------------------------^
compilation aborted for aerotest.f90 (code 1)
James Tursa
James Tursa 2012년 7월 2일
Chris, go ahead and post your m-code snippet for constructing the input and calling the mex routine, and also the mex routine itself and I can look at it.
Chris
Chris 2012년 7월 4일
Ignore the previous code, I think I figured it out and saw how poor the code was.
I'm only having a little trouble understanding how to use the mxGetField. Do you know of any examples of this used with Fortran? The only examples I've seen are with C
mxGetField returns a pointer to an mxArray, which you can then use just like any other pointer to an mxArray. E.g., if on the MATLAB side you did this:
myvar.myfield = 1:3
mymexroutine(myvar)
And if mymexroutine was the Fortran mex routine, then inside this mex routine you could have code like this to get at the data:
use MatlabAPImx
mwPointer mx
mwIndex i
real*8, pointer :: x(:)
i = 1
mx = mxGetField(prhs(1),i,"myfield")
x => fpGetPr1(mx)
The Fortran variable x will point to the 1:3 double data.
Chris
Chris 2012년 7월 4일
편집: Chris 2012년 7월 4일
Thanks James, so for a nested struct like turbinecomponents.hub.position, I would need to use the mxGetField twice, something like:
use MatlabAPImx
mwPointer mx, dx
mwIndex i
real*8, pointer :: x(:), (y:)
i= 1
mx = mxGetField(prhs(1),i,"Hub")
x = fpGetPr1(mx)
dx = mxGetField(prhs(1),i,"Position")
y = fpGetPr1(dx)

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

도움말 센터File Exchange에서 Write C Functions Callable from MATLAB (MEX Files)에 대해 자세히 알아보기

질문:

2012년 6월 26일

Community Treasure Hunt

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

Start Hunting!

Translated by