How to output a mexFunction input without copy
3 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
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?
0 Commenti
Risposte (2)
Bruno Luong
il 8 Ott 2018
Modificato: Bruno Luong
il 8 Ott 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 Commenti
James Tursa
il 8 Ott 2018
Modificato: James Tursa
il 8 Ott 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?
0 Commenti
Vedere anche
Categorie
Scopri di più su Write C Functions Callable from MATLAB (MEX Files) in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!