How to output a mexFunction input without copy

4 views (last 30 days)
How do I define an output vector as an input vector which has been modified in a C routine called by the mex function?
For example, I have the mex function:
/* recurseCh.c */
#include "mex.h"
#include <math.h>
#include <stdlib.h>
void myfunction(double *in0, double *in1, int in2, bool *in3)
{
long i;
for (i = 0; i < in2; i++)
{
if (in3[i])
{
if (in1[i]>in0[i])
{in0[i] = 0;}
else
{in0[i] = in0[i]-in1[i];}
}
}
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
/* DECLARATIONS*/
double *in0, *in1;
bool *in3;
int in2;
/* INPUTS */
in0 = mxGetPr(prhs[0]);
in1 = mxGetPr(prhs[1]);
in2 = mxGetScalar(prhs[2]);
in3 = mxGetLogicals(prhs[3]);
/* OUTPUTS */
plhs[0] = prhs[0]; /* or plhs[0] = in0... or ??? */
/* CALL ROUTINE */
myfunction(in0,in1,in2,in3);
}
The operation
plhs[0] = prhs[0]
seems to be erroneous but shows what I am trying to do.
It can be called in matlab as, for example,
in2 = 210^2;
in0 = rand(in2,1);
in1 = rand(in2,1);
in3 = logical(round(rand(in2,1));
out = recurseCh(in0,in1,in2,in3);
So the function is supposed to change (in3==1) elements of the vector in0 in some way then return the modified vector in0. Previously I just defined plhs[0] as
plhs[0] = mxCreateDoubleMatrix(in2,1,mxREAL);
val = mxGetPr(plhs[0]);
where val is a new vector which I pass to the C routine, but this required modifying the loop so that elements of in0 are copied into val when in3==0.
How do I make the output vector equal to in0 in the most efficient way?

Answers (2)

Bruno Luong
Bruno Luong on 8 Oct 2018
Edited: Bruno Luong on 8 Oct 2018
"How do I define an output vector as an input vector which has been modified in a C routine called by the mex function?"
You are not allowed to do that. This is against MATLAB rule. Reason, 1. the input might share underlined data with other variables. 2. The variable input changes unexpectedly.
Unless if you know what you are doing. In this case you need to create a new mxArray header of LHS, get pointer data point to a data of RHS, update the internal cross-link of the share cycle mxArray.
If you run some old MATLAB version there is an undocumented API function to do that (mxCreateSharedDataCopy).
  2 Comments
Christopher Grose
Christopher Grose on 8 Oct 2018
That's intensely frustrating.
"Unless if you know what you are doing. In this case you need to create a new mxArray header of LHS, get pointer data point to a data of RHS, update the internal cross-link of the share cycle mxArray."
I'm not sure how to do that.
Bruno Luong
Bruno Luong on 8 Oct 2018
Depending on your MATLAB version, follow this link or this link

Sign in to comment.


James Tursa
James Tursa on 8 Oct 2018
Edited: James Tursa on 8 Oct 2018
If you are returning a modified variable, then you basically have three choices:
1) Do it the way you were previously doing it, with mxCreateDoubleMatrix. Yes, this means you will need to manually copy all of the unchanged values as well, but this is necessary. Note that mxCreateDoubleMatrix fills the matrix with 0's to begin with. If you want these 0's as the default then you don't need to have code that sets them to 0's later on.
2) Save the step of filling the initial matrix with 0's by usin mxCreateUninitNumericMatrix instead of mxCreateDoubleMatrix. You will still need to manually copy all of the unchanged values over, but at least it potentially saves some time by avoiding the 0's initialization (if you don't need the 0's).
3) If you know that your variable is not shared with any other variable you might consider modifying the values inplace (basically ignoring the const attribute of prhs). But it is very difficult and sometimes impossible to get this to work correctly, and you have to use unofficial routines and hacks to sniff out the sharing status, so this is NOT RECOMMENDED!
I would advise you use method 1 or 2 above, depending on what you want to have happen with those 0's.
Btw, since in3 is logical, you should probably be using mxLogical instead of bool in your function signature. Probably the same thing of course, but why stray away from the offical MATLAB doc for this?

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Products


Release

R2018a

Community Treasure Hunt

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

Start Hunting!