Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
passing variables between c mex function and predefined subroutine

Subject: passing variables between c mex function and predefined subroutine

From: Jerry

Date: 24 Apr, 2012 13:39:07

Message: 1 of 2

Hello,

I'm new in programming c mex function and I must have done something illegal in passing variables between my mex function and a predefined subroutine. The code regarding the variable passing is pasted below. I was able to compile it quietly but got a segmentation error when I run it. Could anyone please tell me what are wrong in my code? Thank you so much in advance!

//predefined subroutine
void myfunc(float *disc_score_pos_M1, float *disc_score_neg_M1, float *disc_score_pos_M2, float *disc_score_neg_M2,int M, int N, float *az1, float *az2, float ***cov_mat)
{
...
}

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  float *disc_score_pos_M1, *disc_score_neg_M1, *disc_score_pos_M2, *disc_score_neg_M2;
  mwSize mrows,ncols;
  int M, N;
  float *az1,*az2,***cov_mat;
  /* Check for proper number of arguments. */
  if(nrhs!=4) {
    mexErrMsgTxt("Four input arguments required.");
  } else if(nlhs>3) {
    mexErrMsgTxt("Too many output arguments");
  }
  
  /* The input must be four noncomplex double column vector.*/
  
  mrows = mxGetM(prhs[0]);
  ncols = mxGetN(prhs[0]);
  if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
      !(mrows==1 || ncols==1) ) {
    mexErrMsgTxt("Input must be noncomplex vectors.");
  }
  M=mxGetM(prhs[0]);
  N=mxGetM(prhs[1]);
  /* Create matrix for the return argument. */
  plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
  plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
  plhs[2] = mxCreateDoubleMatrix(2,2, mxREAL);
  /* Assign pointers to each input and output. */
  disc_score_pos_M1 = (float *) mxGetPr(prhs[0]);
  disc_score_neg_M1 = (float *) mxGetPr(prhs[1]);
  disc_score_pos_M2 = (float *) mxGetPr(prhs[2]);
  disc_score_neg_M2 = (float *) mxGetPr(prhs[3]);
  
  az1 = (float *) mxGetPr(plhs[0]);
  az2 = (float *) mxGetPr(plhs[1]);
  cov_mat=(float ***) mxGetPr(plhs[2]);
  /* Call the subroutine. */
 myfunc(disc_score_pos_M1, disc_score_neg_M1, disc_score_pos_M2, disc_score_neg_M2, M, N, az1, az2, cov_mat);
}

Subject: passing variables between c mex function and predefined subroutine

From: James Tursa

Date: 24 Apr, 2012 15:06:08

Message: 2 of 2

"Jerry" <mricad@yahoo.no000spppam.com> wrote in message <jn6adr$geq$1@newscl01ah.mathworks.com>...
> Hello,
>
> I'm new in programming c mex function and I must have done something illegal in passing variables between my mex function and a predefined subroutine. The code regarding the variable passing is pasted below. I was able to compile it quietly but got a segmentation error when I run it. Could anyone please tell me what are wrong in my code? Thank you so much in advance!
>
> //predefined subroutine
> void myfunc(float *disc_score_pos_M1, float *disc_score_neg_M1, float *disc_score_pos_M2, float *disc_score_neg_M2,int M, int N, float *az1, float *az2, float ***cov_mat)
> {
> ...
> }
>
> void mexFunction( int nlhs, mxArray *plhs[],
> int nrhs, const mxArray *prhs[] )
> {
> float *disc_score_pos_M1, *disc_score_neg_M1, *disc_score_pos_M2, *disc_score_neg_M2;
> mwSize mrows,ncols;
> int M, N;
> float *az1,*az2,***cov_mat;
> /* Check for proper number of arguments. */
> if(nrhs!=4) {
> mexErrMsgTxt("Four input arguments required.");
> } else if(nlhs>3) {
> mexErrMsgTxt("Too many output arguments");
> }
>
> /* The input must be four noncomplex double column vector.*/
>
> mrows = mxGetM(prhs[0]);
> ncols = mxGetN(prhs[0]);
> if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
> !(mrows==1 || ncols==1) ) {

In the above line you check to see that the 1st input is double. You don't check any of the other inputs.

> mexErrMsgTxt("Input must be noncomplex vectors.");
> }
> M=mxGetM(prhs[0]);
> N=mxGetM(prhs[1]);
> /* Create matrix for the return argument. */
> plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
> plhs[1] = mxCreateDoubleMatrix(1,1, mxREAL);
> plhs[2] = mxCreateDoubleMatrix(2,2, mxREAL);
> /* Assign pointers to each input and output. */
> disc_score_pos_M1 = (float *) mxGetPr(prhs[0]);

Here you take the address of the double data returned by mxGetPr and simply cast the pointer to a float *. This is a basic C programming mistake. Casting the pointer to something else does *not* change the underlying data in any way ... the underlying data is still double.

If you really want the input to be double but use your subroutine as is, you will need to allocate memory blocks that have the same number of elements as the input and then copy the data to the memory blocks, converting each double value to a float value. E.g.,

mwSize i, n;
double *pr;
    :
pr = mxGetPr( prhs[0] );
n = mxGetNumberOfElements( prhs[0] );
az1 = mxMalloc( n * sizeof(*az1) );
for( i=0; i<n; i++ ) {
    az1[i] = pr[i]; /* Convert double values to float values, one by one */
}

> disc_score_neg_M1 = (float *) mxGetPr(prhs[1]);
> disc_score_pos_M2 = (float *) mxGetPr(prhs[2]);
> disc_score_neg_M2 = (float *) mxGetPr(prhs[3]);
>
> az1 = (float *) mxGetPr(plhs[0]);
> az2 = (float *) mxGetPr(plhs[1]);
> cov_mat=(float ***) mxGetPr(plhs[2]);
> /* Call the subroutine. */
> myfunc(disc_score_pos_M1, disc_score_neg_M1, disc_score_pos_M2, disc_score_neg_M2, M, N, az1, az2, cov_mat);
> }

The cov_mat is a bit confusing to me. How is the routine myfunc using cov_mat? Can you show some syntax for this routine using cov_mat? You may have to allocate multiple layers of indexing arrays, fill them in, and pass that to the routine to get things to work, but to be sure I need to see some syntax from myfunc using cov_mat.

James Tursa

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us