Thread Subject: mex variable problems

Subject: mex variable problems

From: Steven

Date: 15 Nov, 2007 21:25:10

Message: 1 of 3

Hi, I want to pass in data from matlab and copy it to a
variable within c++, then do whatever with it... I have run
into a couple problems.
1. The documentation in matlab is terrible on this. They
either use a mxArray throughout the program or a scalar copy
to pass in the data. Have they considered that a majority of
users won't want to use mxArrays ? Its easier to port your
function if you can copy stuff over to arrays.
2. A good way to dynamically allocate memory in c++ (I've
forgotten how)
3. I can't copy data from *prhs to a double array (Vec in
this case) in matlab. I can't even display the output, the
code below when i call it from matlab has this output:

test([1 3 5 4 5])
F1 --- 0
F1 --- 0
F1 --- 0
F1 --- 0
F1 --- 0

void mexFunction(int nlhs, mxArray *plhs[ ],int nrhs,
xArray *prhs[ ]){
int i,j,avg;
mxArray *xData;
double *xValues;
int xrowLen, xcolLen;
double temp;
double Vec[];
int ii,jj;

xData = prhs[0];
xValues = mxGetPr(xData);
xrowLen = mxGetN(xData);
xcolLen = mxGetM(xData);

if(( xrowLen<1)|( xcolLen!=1)){
mexErrMsgTxt("WARNING: ONLY PASS IN ROW VECTOR");
}


for(i=0;i<xrowLen;i++)
{
for(j=0;j<xcolLen;j++)
{
temp = xValues[i+j];
printf("F1 --- %d \n",temp );
                Vec[i][j] = temp;
    }
}
}

Subject: mex variable problems

From: Peter Boettcher

Date: 15 Nov, 2007 21:42:07

Message: 2 of 3

"Steven " <burrguy.athotmailnot@msn.com> writes:

> Hi, I want to pass in data from matlab and copy it to a
> variable within c++, then do whatever with it... I have run
> into a couple problems.

> 1. The documentation in matlab is terrible on this. They
> either use a mxArray throughout the program or a scalar copy
> to pass in the data. Have they considered that a majority of
> users won't want to use mxArrays ? Its easier to port your
> function if you can copy stuff over to arrays.

Most of us find the documentation complete.

I'm not sure what you mean that most users won't want to use mxArrays.
The mxArray is simply the way MATLAB stores arrays, and you get access
to it directly in your mexFunction. The rest of your code should NOT
use mxArrays, but should reference data based on the data pointer stored
in mxArray. You don't need to copy the data out.

I suggest a detailed study of the examples to see the intended usage.

> 2. A good way to dynamically allocate memory in c++ (I've
> forgotten how)

I would use mxMalloc, which lets MATLAB help in the cleanup process if
something goes wrong.

> 3. I can't copy data from *prhs to a double array (Vec in
> this case) in matlab. I can't even display the output, the
> code below when i call it from matlab has this output:

You shouldn't have to copy the data. You can just use xValues as your
array. xValues[0] is the first element, xValues[1] is the next, etc.

More comments below.

> test([1 3 5 4 5])
> F1 --- 0
> F1 --- 0
> F1 --- 0
> F1 --- 0
> F1 --- 0
>
> void mexFunction(int nlhs, mxArray *plhs[ ],int nrhs,
> xArray *prhs[ ]){
> int i,j,avg;
> mxArray *xData;
> double *xValues;
> int xrowLen, xcolLen;
> double temp;
> double Vec[];

Vec is a garbage pointer. You can't store anything to Vec until you
allocate memory for it.

> int ii,jj;
>
> xData = prhs[0];
> xValues = mxGetPr(xData);
> xrowLen = mxGetN(xData);
> xcolLen = mxGetM(xData);
>
> if(( xrowLen<1)|( xcolLen!=1)){
> mexErrMsgTxt("WARNING: ONLY PASS IN ROW VECTOR");
> }
>
>
> for(i=0;i<xrowLen;i++)
> {
> for(j=0;j<xcolLen;j++)
> {
> temp = xValues[i+j];

I know that you've limited j to be always zero, but this expression
isn't right for a 2D access. The 2D to 1D conversion is
[row + column*numRows].

> printf("F1 --- %d \n",temp );

Your print fails because you've told printf to expect an integer, while
you are passing a float. Try %f.

> Vec[i][j] = temp;

As already mentioned, this is invalid since you've not allocated memory
for Vec.


-Peter

Subject: mex variable problems

From: James Tursa

Date: 16 Nov, 2007 08:57:08

Message: 3 of 3


Here are some comments (Peter has already mentioned some of these
which I will repeat)

>1. The documentation in matlab is terrible on this. They
>either use a mxArray throughout the program or a scalar copy
>to pass in the data. Have they considered that a majority of
>users won't want to use mxArrays ? Its easier to port your
>function if you can copy stuff over to arrays.

Well, MATLAB stores data differently than C or C++, Fortran stores
data differently than C or C++, etc. etc. It should be expected that
any other language may store data differently than C or C++. It is not
fair to complain that you have to do something extra to get the data
from another language into yours. Since MATLAB has dynamic typing,
there is bound to be some overhead for their variables to take care of
this. Why should one be surprised at this? MATLAB has kindly provided
functions to extract the data into your C or C++ variables. Most of us
love MATLAB and are willing to live with this. As an analogy, how
would you get or manipulate data from a C++ class? Member functions,
right? What's the big deal about calling functions to get data from
the MATLAB mxArrays when this is what you do all the time for C++
classes to get at the data?

>2. A good way to dynamically allocate memory in c++ (I've
>forgotten how)

You might review "new". But as Peter mentioned, if you use mxMalloc
and mxCalloc you give the MATLAB memory manager a chance to clean up
all of your memory if something goes wrong.

>3. I can't copy data from *prhs to a double array (Vec in
>this case) in matlab. I can't even display the output, the
>code below when i call it from matlab has this output:
>
>test([1 3 5 4 5])
>F1 --- 0
>F1 --- 0
>F1 --- 0
>F1 --- 0
>F1 --- 0
>
>void mexFunction(int nlhs, mxArray *plhs[ ],int nrhs,
>xArray *prhs[ ]){
>int i,j,avg;
>mxArray *xData;
>double *xValues;
>int xrowLen, xcolLen;
>double temp;
>double Vec[];
>int ii,jj;
>
>xData = prhs[0];
>xValues = mxGetPr(xData);
>xrowLen = mxGetN(xData);
>xcolLen = mxGetM(xData);
>
>if(( xrowLen<1)|( xcolLen!=1)){
> mexErrMsgTxt("WARNING: ONLY PASS IN ROW VECTOR");
>}
>
>
>for(i=0;i<xrowLen;i++)
>{
> for(j=0;j<xcolLen;j++)
> {
> temp = xValues[i+j];
> printf("F1 --- %d \n",temp );
> Vec[i][j] = temp;
> }
>}
>}

Many specific comments about your code:

1) You are missing the #include "mex.h" line. You should include this
to make sure you get all the types defined, etc.

2) You misspelled mxArray as xArray in the argument list, and you did
not include the const attribute for prhs[].

3) This line is not the correct way to define an array:

>> double Vec[];

When you declare an array like this the compiler needs to know what
size it is, you can't leave the size blank. It appears that you would
like to declare Vec in such a way that you can later on use the
Vec[i][j] notation in your code for dereferencing a Vec element. You
can't do this in general. The compiler needs to know at compile time
exactly what type of pointer Vec is, meaning the compiler needs to
know the size and type of things that Vec points to at compile time.
You can't declare Vec at compile time to be an arbitrary sized array.
The most you can get away with is declaring a pointer to an array of a
fixed size and then allocate memory for it at run time, for instance:

   double (*Vec)[5];

This declares Vec to be a pointer to an array of doubles of length 5
(but does not allocate any memory for such an array). Then later on in
your code you could allocate memory for Vec and use the Vec[i][j]
notation and it would work correctly. But this *only* works because
the compiler knows at compile time exactly what Vec points to. You
could not do this:

   double (*Vec)[m];

where m was a variable defined at run time, because the size of things
that Vec points to is not known at compile time. So you are going to
have to live with doing the dereferencing arithmetic yourself as Peter
mentioned.

You could declare Vec as a simple pointer to double:

   double *Vec;

and then use a macro to mimic the Vec[i][j] dereferencing (assuming
that the data was copied correctly into the memory that Vec points
to):

#define VEC(i,j) Vec[j+(i)*N]

But this is about as close as you will get to the actual Vec[i][j]
notation for a dynamically allocated size 2-dimensional matrix.

If Vec is pointing directly at a mxArray data location like this:

    Vec = (double *) mxGetPr(prhs[0]);

Then you can simply reverse the indexing scheme of the macro to take
care of it in your C code (since MATLAB stores data column wise):

#define VEC(i,j) Vec[i+(j)*M]

3) You don't do any error checking of the inputs. The user might not
be giving this function what it expects, so the inputs should always
be checked. For example, your very first executable line xData =
prhs[0] will have a problem if the user calls the function with no
input arguments since prhs[0] will be invalid in this case.

4) The following lines are a bit confusing to me. Normally N is the
column and M is the row, but your are reversing that naming convention
with these lines. Not at all sure if this is intentional.

    xrowLen = mxGetN(prhs[0]);
    xcolLen = mxGetM(prhs[0]);

5) Why are you using the bit-wise or operator | in the following line?
It seems to clearly be a logical operation you are doing, not a
bit-wise operation. Admittedly you will wind up with the same logical
result in this particular case, but use of the | operator here instead
of || just doesn't look like good programming.

>> if(( xrowLen<1)|( xcolLen!=1)){

6) The dereferencing line temp = xValues[i+j], as Peter pointed out,
is not correct for an arbitrary size 2-dimensional dereferencing. It
only happens to work logically in your case because one of the
dimensions is 1 (which begs the question why is there a double loop
construct used here when one of them only loops on one value?).

7) You are using the incorrect format, %d, to print a double. You
should use %f. Also, use mexPrintf instead of printf.

>> printf("F1 --- %d \n",temp );

8) The use of more spacing would make your code much more readable.

I have included a working mex file below based on your example. I made
some assumptions about what you were actually after. Note that if you
comment out the following lines the mex function will work just fine
for any sized 2-dimensional array, not just row vectors.

// if( ( n < 1 ) || ( m != 1 ) ){
// mexErrMsgTxt("WARNING: ONLY PASS IN ROW VECTOR");
// }


James Tursa


#include "mex.h"
 
#define VEC(i,j) Vec[j+(i)*n]
#define XVALUES(i,j) xValues[i+(j)*m]
 
void mexFunction(int nlhs, mxArray *plhs[],int nrhs,
                 const mxArray *prhs[])
{
    int i, j;
    double *xValues;
    int m, n;
    double *Vec;
 
    if (nrhs != 1)
        mexErrMsgTxt("One input arguments required.");
    if (nlhs > 0)
        mexErrMsgTxt("Too many output arguments.");
    if( !mxIsDouble(prhs[0]) )
        mexErrMsgTxt("Argument need to be double.");
    if( mxIsEmpty(prhs[0]) )
        mexErrMsgTxt("Argument cannot be empty.");
 
    xValues = mxGetPr(prhs[0]);
    m = mxGetM(prhs[0]);
    n = mxGetN(prhs[0]);
 
    if( ( n < 1 ) || ( m != 1 ) ){
        mexErrMsgTxt("WARNING: ONLY PASS IN ROW VECTOR");
    }
 
    Vec = (double *) mxCalloc(n*m, sizeof(double));
 
    for( i=0; i<m; i++ )
    {
        for( j=0; j<n; j++ )
        {
            VEC(i,j) = XVALUES(i,j);
            mexPrintf("VEC(%d,%d) = %f \n", i, j, VEC(i,j));
        }
    }
 
    mxFree(Vec);
}

Tags for this Thread

Everyone's Tags:

mex, c, copy

Add a New Tag:

Separated by commas
Ex.: root locus, bode

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.

Tag Activity for This Thread
Tag Applied By Date/Time
mex Steven 15 Nov, 2007 16:30:09
c Steven 15 Nov, 2007 16:30:09
copy Steven 15 Nov, 2007 16:30:09
rssFeed for this Thread
 

MATLAB Central Terms of Use

NOTICE: Any content you submit to MATLAB Central, including personal information, is not subject to the protections which may be afforded information collected under other sections of The MathWorks, Inc. Web site. You are entirely responsible for all content that you upload, post, e-mail, transmit or otherwise make available via MATLAB Central. The MathWorks does not control the content posted by visitors to MATLAB Central and, does not guarantee the accuracy, integrity, or quality of such content. Under no circumstances will The MathWorks be liable in any way for any content not authored by The MathWorks, or any loss or damage of any kind incurred as a result of the use of any content posted, e-mailed, transmitted or otherwise made available via MATLAB Central. Read the complete Terms prior to use.

Contact us at files@mathworks.com