I would like to get variable in S-Function (.cpp and wrapper.cpp) from workspace of Matlab.
How can I do that?
Thanks.
You can call into MATLAB from an S-Function using mexCallMATLAB function. Using mexCallMATLAB you can call any MATLAB function from S-Function. Combining this with evalin function you can get a variable from base workspace. The syntax for calling mexCallMATLAB is
int mexCallMATLAB(int nlhs, mxArray *plhs[], int nrhs,
mxArray *prhs[], const char *functionName);
You should set your functionName to "evalin" and the first argument in prhs to be the string "base", and the second argument to be the name of the variable.
Having said that, the recommended way to get a variable into s-function is through parameters. You should add a parameter to s-function and then you can specify your variable as the parameter value. This parameter can be accessed from the s-function using standard s-function API functions like ssGetSFcnParam. See example s-functions mentioned in the doc at https://www.mathworks.com/help/simulink/sfg/ssgetsfcnparam.html.
I have an example:
double Tinit;
mxArray* args[2];
args[0] = mxCreateString("base");
args[1] = mxCreateString("Tinit");
mxArray* out;
mexCallMATLAB(1, &out, 2, args, "evalin"); //eval in workspace base
Tinit = *mxGetPr(out); //gets the double result
You should only use values from workspace when they have a true global meaning.
In my example it is the value of a special step time period, which should not provide with an extra parameter.
Related
I am learning mex files in matlab. I have written this simple code
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]){
double *outData, *inData;
if(nrhs!=2) mexErrMsgTxt("Missing input data.");
inData = mxGetDoubles(prhs[0]);
outData = mxGetDoubles(plhs[0]);
outData[0] = inData[0]+inData[1];
}
But when I try to run it, matlab crashes. The problem is the last line, have you any suggestions why?
Thank you
plhs[0] (i.e. the pointer left hand side of you function call) is the output.
This output variable is not allocated in memory, you just have a pointer to it. So you can not write on it (nor read from it) without creating it first.
So you would need something like
const int ndims = 1; // or whatever dims you want
const mwSize dims[]={1}; // or whatever size you want
// create memory/variable
plhs[0] = mxCreateNumericArray(ndims ,dims,mxDOUBLE_CLASS,mxREAL);
// now it exists
outData = mxGetDoubles(plhs[0])
However, note that if you don't input a 2 length array, inData[1] will not exist, thus causing a RuntimeError, which crashes MATLAB. So its generally good practice to check the length of the array before accessing it.
I want to deploy an m file into an executable. I am using mcc command: mcc -m epidemic.m. Epidemic is my function which takes no arguments and returns a vector and write that vector to txt. Mcc creates epidemic.exe and when I am running that exe it creates the txt file however it seems that it doesnt return values (the return value of .exe). I am trying to run the exe from matlab using:
cmd = ['epidemic.exe '];
system(cmd);
It return cmdout " and status 0. How can I take the returned values of the .exe?
When you compile matlab code like:
function [out1, out2] = epidemic(in1, in2, in3)
%[
...
%]
to standalone (mcc -m epidemeic.m), Matlab produces somehow the following pseudo c-code and compiles it to .exe:
int main(int argc, char** argv)
{
// Load compiled code produced by mcc
HMCRInstance* hInst = loadByteCodeProducedByMccFromResources();
// Similar to have wrote in matlab "epidemic(argv[0], argv[1], ...)"
// 1) Without asking for any argument output
// 2) Argument inputs are passed as strings
int errorCode = mclFevalFromExeArg(hInst, "epidemic", argc, argv);
return errorCode; // only indicates if call to 'mclFEvalFromExeArg'
// succeded, it does not relate to out1, out2 at all.
}
NB: If you want to see the exact code produced by mcc, use mcc -W main -T codegen epidemic.m
So, directly compiling to standalone, you cannot work with outputs of your Matlab function. If you need to play around with output arguments of epidemic, either
[Simple solution] Consider saving outputs to files or display them to shell console using disp (NB: you can use isdeployed in your .m file to check if you're running from matlab or from compiled code).
[Advanced solution] Consider compiling your code to shared library (mcc -l epidemic.m) instead of standalone (mcc -m epidemeic.m)
NB: When you compile your code to shared library, mcc will produce a dll that exports the following function:
extern LIB_epidemeic_C_API
bool MW_CALL_CONV mlxEpidemic(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
nrhs/prhs are the number of input arguments and their values (as mxArray type). And nlhs/plhs are the ouput arguments you want to have when calling epidemic. Up to you to do the marshaling between mxArray and equivalent C native type.
EDIT
As you indicate that epidemic returns a vector of values, you can display them from standalone like this:
function [output] = epidemic(v1, v2, v3)
%[
% When called from system cmd line, v1, v2, v3 are passed
% as string. Here is how to convert them to expected type if required
if (ischar(v1)), v1 = str2double(v1); end
if (ischar(v2), v2 = str2double(v2); end
if (ischar(v3)), v3 = str2double(v3); end
...
output = ...;
...
if (isdeployed())
disp(output);
end
%]
An exe does not have a return value, you need to find another way to transport the data back, for example via console outputs or text files. What you get is the error code and error message.
Is there any way to return a variable number of outputs from a mex function?
One might pack them into a cell, but I wondered wether there is a way, so that they are expanded directly in the output list. Something like
a = mymex(arg1, arg2);
[a, b, c] = mymex(arg1, arg2, 'all');
Of course you can, just like any other MATLAB function:
test_mex.cpp
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
for (int i=0; i<nlhs; i++) {
plhs[i] = mxCreateDoubleScalar(i);
}
}
MATLAB
>> [a,b,c] = test_mex()
a =
0
b =
1
c =
2
You will have to determine how many arguments to return depending on the inputs/outputs, or issue an error if the function is called incorrectly (not enough input, too many outputs, etc..). The example above just accepts any number of output arguments (including none or zero outputs)
Take comma separated lists, which allow use to call functions in interesting ways:
>> out = cell(1,20);
>> [out{:}] = test_mex()
out =
Columns 1 through 11
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]
Columns 12 through 20
[11] [12] [13] [14] [15] [16] [17] [18] [19]
This is like calling the function with 20 output variables:
>> [x1,x2,...,x20] = test_mex()
EDIT:
Just to clarify, MEX-functions act like regular M-functions defined with variable number of inputs and outputs (think function varargout = mymex(varargin)), and the same rules apply; it is up to you to manage access to inputs and create necessary outputs.
For example the previous code can be written as a regular M-function called the same way as before:
function varargout = test_fcn(varargin)
for i=1:nargout
varargout{i} = i-1;
end
end
The difference is that in MEX-files you could crash MATLAB if you try to access something out-of-range, or try to write output beyond what is actually allocated.
Take this example:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
for (int i=0; i<30; i++) { // <--- note 30 as value
plhs[i] = mxCreateDoubleScalar(i);
}
}
Calling the above as:
>> test_mex % careful!
will most likely cause an immediate MATLAB crash. While the same thing done in M-code, will just create unnecessary extra output variables that are destroyed after the call.
As #chappjc explained in his answer, for MEX-files you are always guaranteed to have space for at least one output (plhs is an array of mxArray* of length 1 at a minimum, so it's safe to assign plhs[0] no matter what). If the caller specifies a LHS variable then the output goes into it, otherwise the output is assigned to the special ans variable (of course you can still assign nothing, in case of zero outputs).
The opposite case of not assigning enough output variables is fortunately caught by MATLAB, and throws a regular catch-able error with ID MATLAB:unassignedOutputs (in both MEX and M-functions).
Also, accessing out-of-range inputs will cause an access violation (MATLAB will inform you of that with a big scary dialog, and the prompt will turn to "please restart MATLAB" message). Doing the same in regular M-code, will just throw a regular error "Index exceeds matrix dimensions.", nothing serious!
As you can see, it is very easy for things to go wrong in MEX world (in an unrecoverable way), so you have to pay special attention to validating input/output arguments.
The syntax for calling a MEX function is identical to any other MATLAB function. However, internal to the MEX function, the number of in/out arguments used is determined by the first and third arguments to mexFunction (usually named nlhs and nrhs, can be anything).
Declaration of mexFunction in mex.h (around line 141 in R2014b):
/*
* mexFunction is the user-defined C routine that is called upon invocation
* of a MEX-function.
*/
void mexFunction(
int nlhs, /* number of expected outputs */
mxArray *plhs[], /* array of pointers to output arguments */
int nrhs, /* number of inputs */
const mxArray *prhs[] /* array of pointers to input arguments */
);
This is not unlike the syntax for the standard main functions for C/C++ command line executables, but there are notable differences. Unlike the native command line version (int main(int argc, const char* argv[])), the count and pointer array does not include the name of the function (argv[0] is usually the name of the executable program file), and with mexFunction there are parameters for output arguments as well as input.
The naming for nlhs and nrhs should be clear. HINT: In mathematics, an equation has a left hand side and a right hand side.
An important but easily overlooked quality of mexFunction I/O handling pertains to MATLAB's special ans variable, the place where function outputs (often) go if you don't assign to a variable. In a MEX file, you need to remember the following when checking nlhs. If nlhs=0, you can and must still write to plhs[0] for ans to be used. It's documented, just barely, in Data Flow in MEX-Files. Consider what happens with the following code:
// test_nlhs.cpp
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
for (int i=0; i<nlhs; ++i)
plhs[i] = mxCreateDoubleScalar(i);
}
Outputs:
>> test_nlhs
>> [a,b] = test_nlhs
a =
0
b =
1
There's no output to ans because the logic with nlhs prevents it from assigning to plhs[0]. Now this code:
// test_nlhs.cpp
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if (nlhs==0) {
mexPrintf("Returning special value to ""ans"".\n");
plhs[0] = mxCreateDoubleScalar(-1);
} else {
mexPrintf("Returning to specified workspace variables.\n");
for (int i=0; i<nlhs; ++i)
plhs[i] = mxCreateDoubleScalar(i);
}
}
Outputs
>> test_nlhs
Returning special value to ans.
ans =
-1
>> [a,b] = test_nlhs
Returning to specified workspace variables.
a =
0
b =
1
It's certainly doesn't have to be a special value, and it should usually be the same first output argument, but I'm illustrating how you recognize the calling syntax.
In Matlab, I have a a process (a data acquisition that is using calllib, but this is not important) which returns me pointers (libpointer) to a large array. I would like to use these arrays in a MEX file. If I have a libpointer X to this array, how can I use it in the MEX file?
Of course, there is the possibility to assign this to a new variable, like
A = X.Value;
But I suppose that this assignment will copy the array, what I do not want.
So my question, is there a way to use the libpointer (=the array's address) as an input argument of the MEX function and to retrieve the values from this input argument in MEX? As prhs[] is supposed to be a mxArray, I don't know how this should work.
Any help would be appreciated!
Update 2014-08-11: minimal example code:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
(void) plhs;
mexPrintf("%d \n",prhs[0]); // gives back e.g. "7209090"
mexPrintf("%p \n",prhs[0]); // gives back e.g. "00000142006E0082"
}
And the Matlab code would then be like:
mex cfunction.c
pv = libpointer('doublePtr',112);
cfunction(pv)
I am more of a Matlab programmer, and have not used C in years! Now I have to write some code in C and have it called from Matlab via the mexFunction command. So far so good. But my code requires many function calls where both the argument and the return values are arrays. For this I am using pointer returns. But I have run into about a million difficulties, once one is fixed another is created.
example of the sort code is as follows (the actual code is massive)
#include "mex.h"
#include "math.h"
int Slength=95;
double innercfunction(double q,double y)
{
int i;
double X;
X=q*y;
}
double *c1function(double q,double Sim[])
{
double *F12=malloc(Slength);
int i;
double vdummy,qdummy;
qdummy=q;
for(i=0;i<Slength;i++)
{
vdummy=Sim[i];
F12[i]=innercfunction(qdummy,vdummy);
}
return F12;
}
void mexFunction(int nlhs, mxArray *prhs[],int nrhs,const mxArray *plhs[])
{
double *q=mxGetPr(prhs[0]);
double *Sim=mxGetPr(prhs[1]);
double *SS=c1function(q,Sim);
}
i save it as help_file.c and compile from THE MATLAB workspace as:
mex -g help_file.c
to which i get the following error:
help_file.c: In function ‘mexFunction’:
help_file.c:38: error: incompatible type for argument 1 of ‘c1function’
help_file.c:17: note: expected ‘double’ but argument is of type ‘double *’
i tried initially passing Sim[i] instead of vdummy, that did not work which is why I defined the dummy variable in the first place.
I imagine this is a trivial problem, but I would still appreciate peoples help on this.
The prototype of clfunction requires you to pass a scalar double as the first argument; you're passing a pointer-to-double q, hence the compiler error. Are you expecting prhs[0] to contain a scalar? If so, you could use q[0] to extract the value; or else, you could use mxGetScalar(prhs[0]) which returns a scalar-double ( http://www.mathworks.com/help/techdoc/apiref/mxgetscalar.html ).
However, I'm not sure that fixing that would make your mex file work as expected. I would suggest taking some time to read the mex examples here: http://www.mathworks.com/support/tech-notes/1600/1605.html
In particular, your current mex file isn't going to produce any output arguments since you aren't assigning to the left-hand side plhs.