Azzera filtri
Azzera filtri

How to input and output variable in mex function

30 visualizzazioni (ultimi 30 giorni)
I want to input an array into a mex function, modify the array, and then output the array without changing the variable name. My attempts to do this have failed. The code runs if I remove the lines:
b = mxGetPr(plhs[1]);
d = mxGetPr(plhs[2]);
but I want to return the values of b and d... I have also tried
plhs[1] = b;
plhs[2] = d;
Also, it is not acceptable to copy the array into another variable which can then be output.
Here is my failing mex function:
#include "mex.h" /*The mex library*/
#include <math.h>
#include <stdlib.h>
void runfunc(double *a, double *b, double *c, double *d, double *x, long ynum)
{
long i;
double w;
for (i = 1; i<ynum; i++)
{
w = a[i]/b[i-1];
b[i] = b[i]-w*c[i-1];
d[i] = d[i]-w*d[i-1];
}
x[ynum-1] = d[ynum-1]/b[ynum-1];
for (i = ynum-2; i!=-1; i--)
{
x[i] = (d[i]-c[i]*x[i+1])/b[i];
}
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/* DECLARATIONS*/
double *a, *b, *c, *d, *x;
long ynum;
/* INPUTS */
a = mxGetPr(prhs[0]);
b = mxGetPr(prhs[1]);
c = mxGetPr(prhs[2]);
d = mxGetPr(prhs[3]);
ynum = mxGetScalar(prhs[4]);
/* OUTPUTS */
plhs[0] = mxCreateDoubleMatrix(ynum,1,mxREAL);
x = mxGetPr(plhs[0]);
b = mxGetPr(plhs[1]);
d = mxGetPr(plhs[2]);
/* CALL ROUTINE */
runfunc(a,b,c,d,x,ynum);
}

Risposta accettata

James Tursa
James Tursa il 30 Nov 2018
Modificato: James Tursa il 30 Nov 2018
Some issues:
b = mxGetPr(plhs[1]);
d = mxGetPr(plhs[2]);
The above lines crash MATLAB when you try to use b and d downstream because plhs[1] and plhs[2] haven't been created. The plhs variables are output variables that you the programmer need to create before you access them. So, create them first. E.g.,
if( nlhs < 3 ) {
mexErrMsgTxt("Need to specify three output variables");
}
plhs[0] = mxCreateDoubleMatrix(ynum,1,mxREAL);
plhs[1] = mxDuplicateArray(prhs[1]);
plhs[2] = mxDuplicateArray(prhs[3]);
x = mxGetPr(plhs[0]);
b = mxGetPr(plhs[1]);
d = mxGetPr(plhs[2]);
Then of course you don't need these earlier lines at all:
b = mxGetPr(prhs[1]);
:
d = mxGetPr(prhs[3]);
And, to make your mex routine more robust, you should be checking the number and class and size of all of your inputs before using them downstream in your code.
  2 Commenti
Kinan Bezem
Kinan Bezem il 2 Feb 2021
I have a similar question, but my setup is a bit different, I'm trying to input and output fail and dualfail.
It doesn't like the mx duplicate array lines
#include "fintrf.h"
C Gateway routine
subroutine mexFunction(nlhs, plhs, nrhs, prhs)
C Declarations
implicit none
C mexFunction arguments:
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
C Function declarations:
mwPointer mxCreateDoubleMatrix
mwPointer mxDuplicateArray
mwPointer mxGetPr
mwPointer mxGetM, mxGetN
integer mxIsNumeric
C Pointers to input/output mxArrays:
mwPointer coord_pr,dualnumfam_pr,dualfail_pr,dualpointfam_pr
mwPointer dualnodefam_pr,totnode_pr,width_pr,scr0_pr,vol_pr,bc_pr
mwPointer disp_pr,numfam_pr,nodefam_pr,pointfam_pr,fail_pr
mwPointer dmgpar1_pr,dmgpar2_pr, pforce_pr, dualpforce_pr
C Array information:
mwPointer m, n, x, y, u, l
integer mm, nn
mwSize size, row, sizes
C Arguments for computational routine:
real*8 coord(600000), dualnumfam(190000)
real*8 dualfail(40000000), dualpointfam(190000)
real*8 dualnodefam(40000000),totnode(1) ,width(1)
real*8 scr0(190000), vol(190000), bc(190000)
real*8 disp(600000), numfam(190000),nodefam(40000000)
real*8 pointfam(190000),fail(40000000)
real*8 dmgpar1(190000),dmgpar2(190000)
real*8 pforce(600000),dualpforce(600000)
character*200 msg
character*20 fmt
character*10 sm, sn, sx, sy
C-----------------------------------------------------------------------
C Check for proper number of arguments.
if (nrhs .ne. 15) then
call mexErrMsgIdAndTxt ('MATLAB:test:nInput',
+ 'One inputs required.')
endif
C Validate inputs
C Check to see both inputs are numeric.
if (mxIsNumeric(prhs(1)) .ne. 1) then
call mexErrMsgIdAndTxt ('MATLAB:test:NonNumeric1',
+ 'Input # 1 is not a numeric.')
endif
C Check that input #1 is a scalar.
m = mxGetM(prhs(1))
n = mxGetN(prhs(1))
size = m*n
x = mxGetM(prhs(3))
y = mxGetN(prhs(3))
sizes=x*y
u = mxGetM(prhs(5))
fmt = '(I8)'
write (sm,fmt) m
write (sn,fmt) n
write (sx,fmt) x
write (sy,fmt) y
msg = 'm=' // trim(sm) // ',\t n=' // trim(sn) // '\n'
call mexPrintf(trim(msg))
msg = 'x=' // trim(sx) // ',\t y=' // trim(sy) // '\n'
call mexPrintf(trim(msg))
C Create matrix for the return argument.
coord_pr = mxGetPr(prhs(1))
dualnumfam_pr = mxGetPr(prhs(2))
dualfail_pr = mxGetPr(prhs(3))
dualpointfam_pr = mxGetPr(prhs(4))
dualnodefam_pr = mxGetPr(prhs(5))
totnode_pr = mxGetPr(prhs(6))
width_pr = mxGetPr(prhs(7))
scr0_pr = mxGetPr(prhs(8))
vol_pr = mxGetPr(prhs(9))
bc_pr = mxGetPr(prhs(10))
disp_pr = mxGetPr(prhs(11))
numfam_pr = mxGetPr(prhs(12))
nodefam_pr = mxGetPr(prhs(13))
pointfam_pr = mxGetPr(prhs(14))
fail_pr = mxGetPr(prhs(15))
dmgpar1_pr = mxGetPr(plhs(1))
dmgpar2_pr = mxGetPr(plhs(2))
pforce_pr = mxGetPr(plhs(3))
dualpforce_pr = mxGetPr(plhs(4))
fail_pr = mxGetPr(plhs(5))
dualfail_pr = mxGetPr(plhs(6))
plhs(1) = mxCreateDoubleMatrix(m,1,0)
plhs(2) = mxCreateDoubleMatrix(m,1,0)
plhs(3) = mxCreateDoubleMatrix(m,3,0)
plhs(4) = mxCreateDoubleMatrix(m,3,0)
plhs(4) = mxCreateDoubleMatrix(m,200,0)
plhs(5) = mxCreateDoubleMatrix(m,200,0)
plhs(5) = mxDuplicateArray(fail_pr)
plhs(6) = mxDuplicateArray(dualfail_pr)
C Load the data into Fortran arrays.
call mxCopyPtrToReal8(coord_pr,coord,size)
call mxCopyPtrToReal8(dualnumfam_pr,dualnumfam,m)
call mxCopyPtrToReal8(dualfail_pr,dualfail,sizes)
call mxCopyPtrToReal8(dualpointfam_pr,dualpointfam,m)
call mxCopyPtrToReal8(dualnodefam_pr,dualnodefam,u)
call mxCopyPtrToReal8(totnode_pr,totnode,1)
call mxCopyPtrToReal8(width_pr,width,1)
call mxCopyPtrToReal8(scr0_pr,scr0,m)
call mxCopyPtrToReal8(vol_pr,vol,m)
call mxCopyPtrToReal8(bc_pr,bc,m)
call mxCopyPtrToReal8(disp_pr,disp,size)
call mxCopyPtrToReal8(numfam_pr,numfam,m)
call mxCopyPtrToReal8(nodefam_pr,nodefam,u)
call mxCopyPtrToReal8(pointfam_pr,pointfam,m)
call mxCopyPtrToReal8(fail_pr,fail,sizes)
call mxCopyPtrToReal8(dmgpar1_pr,dmgpar1,m)
call mxCopyPtrToReal8(dmgpar2_pr,dmgpar2,m)
call mxCopyPtrToReal8(pforce_pr,pforce,size)
call mxCopyPtrToReal8(dualpforce_pr,dualpforce,size)
C Call the computational subroutine.
call body(coord,dualnumfam,dualfail,dualpointfam,dualnodefam,
+ totnode,width,scr0,vol,bc,disp,numfam,nodefam,pointfam,fail
+ ,m,n,dmgpar1,dmgpar2,pforce,dualpforce,u)
C Load the output into a MATLAB array.
call mxCopyReal8ToPtr(dmgpar1,dmgpar1_pr,m)
call mxCopyReal8ToPtr(dmgpar2,dmgpar2_pr,m)
call mxCopyReal8ToPtr(pforce,pforce_pr,size)
call mxCopyReal8ToPtr(dualpforce,dualpforce_pr,size)
call mxCopyReal8ToPtr(fail,fail_pr,sizes)
call mxCopyReal8ToPtr(dualfail,dualfail_pr,sizes)
James Tursa
James Tursa il 2 Feb 2021
Modificato: James Tursa il 3 Feb 2021
@Kinan: Please delete this comment and instead open up a new Question, since the issues may be totally different than this original post, and since yours is a Fortran question. Thanks.
The issue with your mxDuplicateArray( ) calls is that you are passing in data pointers when you should be passing in mxArray pointers. Also, you access the plhs( ) variables before you create them. Both of these problems will cause a MATLAB crash.

Accedi per commentare.

Più risposte (0)

Community Treasure Hunt

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

Start Hunting!

Translated by