error messages when writing Mex files, problem with array output from functions? - matlab

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.

Related

Get variable in S Function from Workspace

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.

Deploy an matlab file to executable

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.

MATLAB, mex files, Fortran, warnings and errors

I'm not quite seeing the issue I'm having, and I've tried suggestions I've seen in other forum posts. I am trying to write a (fortran) mex file, per request of my boss. However, I was getting warnings when passing a matrix to my computational routine. If I ignored the warning, my MATLAB shut down. So now I'm trying a simpler program, an inner product. However, I am still getting the warning: "Expected a procedure at (1)" where (1) is at 'call innerProd(x,y,c)' underneath the x. I'm not sure what that means... I've included my code.
#include "fintrf.h"
C======================================================================
#if 0
C
C innerProd.F
C .F file needs to be preprocessed to generate .for equivalent
C
#endif
C
C innerProd.F
C calculates the inner product
C This is a MEX file for MATLAB.
C Copyright 1984-2011 The MathWorks, Inc.
C $Revision: 1.12.2.9 $
C======================================================================
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, mxGetPr,mxGetM, mxGetData
integer:: mxIsNumeric
C Pointers to input/output mxArrays:
mwPointer:: x_ptr, y_ptr, c_ptr
C Array information:
mwSize:: m
C Arguments for computational routine:
real*8:: x,y,c
C----------------------------------------------------------------------
C Check for proper number of arguments.
if (nrhs .ne. 2) then
call mexErrMsgTxt('Error.')
elseif (nlhs .ne. 1) then
call mexErrMsgTxt('One output required.')
endif
C Check to see if inputs are numeric.
if (mxIsNumeric(prhs(1)) .ne. 1 ) then
call mexErrMsgTxt('Input # 1 is not a numeric array.')
elseif (mxIsNumeric(prhs(2)) .ne. 1) then
call mexErrMsgTxt('Input #2 is not a numeric array.')
endif
C Find dimensions of mxArrays
m=mxGetM(prhs(1))
C create Fortran arrays from the input arguments
x_ptr=mxGetData(prhs(1))
call mxCopyPtrToReal8(x_ptr,x,m)
y_ptr= mxGetData(prhs(2))
call mxCopyPtrToReal8(y_ptr,y,m)
C create matrix for the return argument
plhs(1) =mxCreateDoubleMatrix(1,1,0)
c_ptr= mxGetPr(plhs(1))
C Call the computational subroutine.
call innerProd(x,y,c)
C Load the output into a MATLAB array.
call mxCopyReal8ToPtr(c, c_ptr, 1)
return
end subroutine mexFunction
C----------------------------------------------------------------------
C Computational routine
subroutine innerProd(x,y,c)
implicit none
real*8:: x,y,temp,c
integer:: i,m
do i=1,m
temp=temp+x(i)*y(i)
end do
c = temp
return
end subroutine innerProd
I'm just learning this for the first time, and I would appreciate any suggestions. Even if it is where to look for solutions. I've looked through MATLAB mex Fortran aids online. There isn't any help there. I can't get the function to run, so I can't use print statements which is a good way to debug. I think mex has a print function, I will try to get that to work.
Thank you!
The main problem is that you haven't anywhere declared the arguments of innerProd as arrays. That holds for the actual arguments x and y in the subroutine mexFunction and the dummy arguments x and y in innerProd itself.
So, in innerProd the expression x(i) isn't referencing the i-th element of the real*8 array x, but the real*8 result of the function x with argument i. As the x you've passed isn't a function (procedure), this is an error.
There are ways to solve this, but all involve declaring the dummy arguments as arrays. Which brings up another point.
You have in innerProd
integer:: i,m
do i=1,m
temp=temp+x(i)*y(i)
end do
where m is not defined. Crucially, from mexfunction you're expecting the compiler to know that m is the size of the arrays x and y: this isn't true. m is a variable local to innerProd. Instead you may want to pass it as an argument to the subroutine and use that to dimension the arrays:
subroutine innerProd(x,y,c,m)
implicit none
integer :: m
real*8:: x(m),y(m),temp,c
...
end subroutine
[You could, of course, use assumed-shape arrays (and the SIZE intrinsic), but that's an additional complication requiring more substantial changes.] You also need to think about how to declare arrays appropriately in mexfunction, noting that the call to mxCopyPtrToReal8 also requires an array argument.
I couldn't get the Fortran code to work for innerProd, but I did get C code to work. I recommend, if you are having issues with Fortran, to use C. It seems that Matlab is more flexible when it comes to mex files and C. Here is the code:
#include "mex.h"
/*
* innerProd.c
*
*Computational function that takes the inner product of two vectors.
*
*Mex-file for MATLAB.
*/
void innerProd(double *x, double *y,double *c,int m){
double temp;
int i;
for(i=0; i < m; i++){
temp = temp + x[i]*y[i];
}
*c=temp;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *x, *y, *c;
size_t m;
/*check for proper number of arguments.*/
if(nrhs != 2){
mexErrMsgIdAndTxt("MATLAB:innerProd:invalidNumInputs","Two input required.");
}
/*The input must be a noncomplex double vector.*/
m = mxGetM(prhs[0]);
if(!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) || m==1){
mexErrMsgIdAndTxt("MATLAB:innerProd:inputNotRealDouble","Input must be noncomplex double vector");
}
/*create return argument */
plhs[0] = mxCreateDoubleMatrix(1,1,0);
c=mxGetPr(plhs[0]);
/*Assign pointers to each input and output. */
x = mxGetPr(prhs[0]);
y=mxGetPr(prhs[1]);
/*call subroutine*/
innerProd(x,y,c,m);
}
I will still take suggestions on the Fortran code above, though. I'd like to know how to get it to work. Thanks!

libpointer as input for MEX function in Matlab

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)

Matlab mex c: strange calculation error with long double

I've noticed a problem on some C code that I'm writing where when I multiply two long doubles I sometimes get lower than expected accuracy. I've isolated an example below, note that this is an mex file for use in matlab. Repeating exactly the same code in pure c results in the expected behaviour.
#include <mex.h>
#include <stdint.h>
typedef int32_t q0_31; // 32 bit signed fixed point number with 31 fractional bits
// conversion to long double from q0_31
long double q0_31_to_ldouble(q0_31 d) {
return d/2147483648.0L;
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
mwSize nInputs = 0;
mwSize nOutputs = 0;
q0_31 b;
long double b_ld;
/* check for proper number of arguments */
if( nrhs!=nInputs )
mexErrMsgIdAndTxt("filter_interface:nrhs","wrong number of inputs!");
if( nlhs!=nOutputs )
mexErrMsgIdAndTxt("filter_interface:nlhs","wrong number of outputs!");
// random value for b
b = 0x81948b0e;
// convert to long double directly
b_ld = b/2147483648.0L;
mexPrintf("Inline calculation...\n");
mexPrintf("b_ld:\t%0.16LA\n",b_ld);
mexPrintf("b_ld^2:\t %0.16LA\n",b_ld*b_ld);
// repeat with sub function
b_ld = q0_31_to_ldouble(b);
mexPrintf("Exactly the same with sub function...\n");
mexPrintf("b_ld:\t%0.16LA\n",b_ld);
mexPrintf("b_ld^2:\t %0.16LA\n",b_ld*b_ld);
}
After compilation, this is the output I get from the code:
Inline calculation...
b_ld: -0XF.CD6E9E4000000000P-4
b_ld^2: 0XF.9B7D0E4BEE0D3100P-4
Exactly the same with sub function...
b_ld: -0XF.CD6E9E4000000000P-4
b_ld^2: 0XF.9B7D0E4BEE0D0000P-4
It is totally bizarre, the value returned by the function is exactly the same as the inline calculation. Yet when I square it I get a different result.
As I only get this behaviour in the mex and not when I compile the same code directly with gcc I thought it might be due to some strange compiler flag that matlab uses. But I have not been able to find anything.
Any ideas? Can anyone replicate?
MATLAB Version: 7.14.0.739 (R2012a)
gcc: 4.8.1-10ubuntu9