1 view (last 30 days)

Show older comments

I've spent a week on the following problem and I can't for the life of me figure it out! I'm going to be as brief as possible with the code and chop out irrelevant lines but it should be clear as to my problem. For starters, I'm using Matlab in combination with C, which communicates via mex files. Without further ado...

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

{

static double *U

plhs[4] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL);

U = (double*)mxGetPr(plhs[4]);

/* C code which solves for "U" based on a number of other input variables*/

solve(U,...,...,...)

/* C code which solves for "U" based on a number of other input variables*/

derivative(U,...,...,...)

}

After execution, everything works fine and I have the value for the derivative of "U". I then wanted to compare solvers so I'm swapping out the "solve(U)" for a Matlab function which I call via "mexCallMATLAB". Here is where I get lost

(Again I removed irrelevant variables)

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

{

static double *U

plhs[4] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL);

U = (double*)mxGetPr(plhs[4]);

/* Call MATLAB solver */

mxArray *Uin[8],*Uout[2];

Uin[0] = mxCreateNumericArray(2,dims,mxSINGLE_CLASS,mxREAL);

memcpy(mxGetPr(Uin[0]),(some variable),m*n*sizeof(float));

yes there are 8 inputs...I just removed for simplicity

mexCallMATLAB(2,Uout,8,Uin,"my_matlab_solver");

I then check the results of "Uout" with the following:

mexCallMATLAB(0,NULL,1,&Uout[0],"plot_variable");

Everything works out great, but the "C" code that later calls on the variable "U" to find it's derivative does not work.

plhs[4] = Uout[0];

/* C code which solves for "U" based on a number of other input variables*/

derivative(U,...,...,...)

}

I can not figure out how to assign "Uout[0]" to "U". I thought by setting plhs[4] = Uout[0] then U would point to the results from "my_matlab_solver" but it does not. There are no compile errors.

Is there easier way where I can assign the output of "my_matlab_solver" directly to "U" with out having to make a mxArray for the output? This whole MEX thing seems a lot more complicated than it needs to be. Thanks for you help!

************************************************************************** ************************************************************************** **************************************************************************

EDIT: I'm going to be very blunt

I have a variable called "U" which is defined as follows

U = (double*)mxGetPr(plhs[4]);

How do I assign the output from this mexCallMATLAB

mexCallMATLAB(2,Uout,8,Uin,"my_matlab_solver");

to "U"? I tried this; plhs[4] = Uout[0]; but it does not work. Don't worry about the rest of the code it's fine. My problem is strictly related to assigning the output of mexCallMATLAB to a variable defined as "U" is above.

Jan
on 25 May 2013

You cannot and should assign the output of the Matlab call to U. The output of the Matlab call is an mxArray variable and U is a pointer to a double array. Perhaps you want to obtain another pointer to the data of the output.

It seems, like the concept of the mxArray variables and the pointers to their contents is not clear to you already.

It is hard for me to give advices of the code, because the code is posted in parts and distributed over several comments and sections. I do not think that the rest of the code is fine, because the confusion with the mxArray plhs[4] and pointers to data appear repeatedly.

James Tursa
on 26 May 2013

Edited: James Tursa
on 26 May 2013

Try this. It works for me with some simple test code for FILLAB, my_matlab_solver, and plot_variable. I added some comments where you have memory leaks and type issues, and put in some code for variable class and size checks.

/* Did you include string.h? (for memcpy) */

void mexFunction(int nlhs, mxArray *plhs[],

int nrhs, const mxArray *prhs[])

{

static double *A,*B;

mwSize dims[2] = {5,10}; // Use mwSize here, not int.

static double *U,*V;

mxArray *APPLE[1];

mxArray *Uin[2],*Uout[2];

if( nlhs < 2 ) {

mexErrMsgTxt("Not enough outputs.");

}

A = mxGetPr(mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL)); // MEMORY LEAK!

B = mxGetPr(mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL)); // MEMORY LEAK!

// In the above two lines, you lose the pointers to the mxArrays! Bad practice!

/* C code which fills A and B */

FILLAB(A,B);

Uin[0] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL);

Uin[1] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL);

memcpy(mxGetPr(Uin[0]),A,5*10*sizeof(double));

memcpy(mxGetPr(Uin[1]),B,5*10*sizeof(double));

Uout[0] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL); // MEMORY LEAK!

Uout[1] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL); // MEMORY LEAK!

// In the above two lines, the mxArrays created are lost by the subsequent

// call to mexCallMATLAB, which OVERWRITES the pointers in Uout[0] and Uout[1].

// This is not good programming practice! Just DELETE these two lines entirely!

mexCallMATLAB(2,Uout,2,Uin,"my_matlab_solver"); // This CREATES new outputs in Uout.

// Note, you could use plhs in the 2nd argument above and skipped the following

// two lines assigning Uout to plhs.

plhs[0] = Uout[0];

plhs[1] = Uout[1]; // Need nlhs >= 2 in order for this to work.

U = mxGetPr(plhs[0]);

V = mxGetPr(plhs[1]); // Need nlhs >= 2 in order for this to work.

APPLE[0] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL);

if( !mxIsDouble(plhs[1]) || mxIsSparse(plhs[1]) || mxGetNumberOfElements(plhs[1]) < 50 ) {

mexErrMsgTxt("plhs[1] is not full double class with 50 or more elements");

}

if( !mxIsDouble(plhs[0]) || mxIsSparse(plhs[0]) || mxGetNumberOfElements(plhs[0]) < 50 ) {

mexErrMsgTxt("plhs[0] is not full double class with 50 or more elements");

}

memcpy(mxGetPr(APPLE[0]),V,5*10*sizeof(double));

/*APPLE[0] = plhs[1]; */

mexCallMATLAB(0,NULL,1,&APPLE[0],"plot_variable");

// Note, you can just use APPLE in the 3rd argument above. No need to use &APPLE[0].

}

James Tursa
on 24 May 2013

Edited: James Tursa
on 24 May 2013

Your words from above:

EDIT: I'm going to be very blunt

I have a variable called "U" which is defined as follows

U = (double*)mxGetPr(plhs[4]);

How do I assign the output from this mexCallMATLAB

mexCallMATLAB(2,Uout,8,Uin,"my_matlab_solver");

to "U"? I tried this;

plhs[4] = Uout[0];

but it does not work. Don't worry about the rest of the code it's fine. My problem is strictly related to assigning the output of mexCallMATLAB to a variable defined as "U" is above.

-----------------------------------------------------------------------------

If Uout[0] is indeed assigned by the mexCallMATLAB call, then the plhs[4] = Uout[0] line should have worked, assuming that you do the U = mxGetPr(plhs[4]) line after assigning plhs[4]. In orher words, this order should work:

mexCallMATLAB(2,Uout,8,Uin,"my_matlab_solver");

plhs[4] = Uout[0];

U = mxGetPr(plhs[4]);

And, as Jan has already pointed out, you need to delete a couple of lines related to your first plhs[4] = etc to avoid a memory leak.

James Tursa
on 26 May 2013

The difference between the two above is as follows:

> V = mxGetPr(plhs[1]);

This gets the data pointer from the mxArray plhs[1], which must have a valid mxArray in it or the routine will probably crash MATLAB. This data pointer value is assigned to the variable V. I.e., this statement is just a pointer value assignment to a variable. The data itself is not examined or copied.

> memcpy(mxGetPr(APPLE[0]),V,5*10*sizeof(double));

This copies 50 double values from V into the data memory of the mxArray APPLE[0]. V must point to valid double memory of at least 50 elements and APPLE[0] must already be created to have at least 50 double elements of data or MATLAB will crash.

> APPLE[0] = plhs[1];

This copies the pointer value of plhs[1] into the pointer value of APPLE[0]. It doesn't do anything more. Nothing is checked, no attempt is made to examine the underlying mxArray, and no data is examined or copied. The statement is simply the assignment of a pointer value to a variable.

Jan
on 23 May 2013

I do not understand, what you want to achieve:

plhs[4] = mxCreateNumericArray(2,dims,mxDOUBLE_CLASS,mxREAL);

U = (double*)mxGetPr(plhs[4]);

Now U is the pointer to the data of the 5th output argument.

plhs[4] = Uout[0];

Now the 5th output is overwritten, which means a memory leak (which is caught automatically when the mex function is left fortunately).

But what does >>assign "Uout[0]" to "U"<< mean now? Do you want to get the pointer to the data of Uout[0] again?

U = mxGetPr(Uout[0]);

Btw., mxGetPr replies a double * already, such that you do not have to cast it.

Jan
on 25 May 2013

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

Start Hunting!