Pergunta

I've been at this for a couple days now, have tried every variation I can think of, and looked at countless examples. I just can't get it working.

I'm trying to make a mexFunction to call from matlab. This mexFunction calls into another C function I have, lets call it retrieveValues, and returns an array and the length of that array. I need to return both of those back to the matlab function, which as I understand it, means I need to put them in the plhs array.

I call my mexFunction from matlab like this:

[foofooArray, foofooCount] = getFoo();

Which to my understanding, means that nlhs = 2, plhs is an array of length 2, nrhs = 0, and prhs just a pointer.

Here's my code for the mexFunction:

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray* prhs[]) 
{
    foo* fooArray
    int fooCount

    plhs = mxCreateNumericMatrix(1, 2, mxUINT64_CLASS, mxREAL);  
    //feels like I shouldn't need this

    retrieveValues(&fooArray, &fooCount);

    plhs[0] = fooArray;
    plhs[1] = fooCount;
}

Running the matlab program gets me One or more output arguments not assigned during call

I've tested and confirmed that the values are being returned from retrieveValues correctly.

Foi útil?

Solução

You are correct that the plhs = mxCreateNumericMatrix(...) is not needed. Also, note that nlhs is the number of left-hand-sides you supply in MATLAB - so in your case, you're calling it with 2 left-hand-sides. Here's how to return trivial scalar values:

plhs[0] = mxCreateDoubleScalar(2);
plhs[1] = mxCreateDoubleScalar(3);

To handle your actual return values, you'll need to do something to copy the values out of foo and into a newly-created mxArray. For example, if your function returned doubles, you might do this:

double * values;
int numValues;
myFcn(&values, &numValues);

/* Build a 1 x numValues real double matrix for return to MATLAB */
plhs[0] = mxCreateDoubleMatrix(1, numValues, mxREAL);

/* Copy from 'values' into the data part of plhs[0] */
memcpy(mxGetPr(plhs[0]), values, numValues * sizeof(double));

EDIT Of course someone somewhere needs to de-allocate values in both my example and yours.

EDIT 2 Complete executable example code:

#include <string.h>
#include "mex.h"

void doStuff(double ** data, int * numData) {
    *numData = 7;
    *data = (double *) malloc(*numData * sizeof(data));
    for (int idx = 0; idx < *numData; ++idx) {
        (*data)[idx] = idx;
    }
}

void mexFunction( int nlhs, mxArray * plhs[],
                  int nrhs, const mxArray * prhs[] ) {
    double * data;
    int numData;
    doStuff(&data, &numData);
    plhs[0] = mxCreateDoubleMatrix(1, numData, mxREAL);
    memcpy(mxGetPr(plhs[0]), data, numData * sizeof(double));
    free(data);
    plhs[1] = mxCreateDoubleScalar(numData);
}

Outras dicas

Here is an example:

testarr.cpp

#include "mex.h"
#include <stdlib.h>
#include <string.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray* prhs[])
{
    // validate number of arguments
    if (nrhs != 0 || nlhs > 2) {
        mexErrMsgTxt("Wrong number of arguments");
    }

    // create C-array (or you can recieve this array from a function)
    int len = 5;
    double *arr = (double*) malloc(len*sizeof(double));
    for(int i=0; i<len; i++) {
        arr[i] = 10.0 * i;
    }

    // return outputs from MEX-function
    plhs[0] = mxCreateDoubleMatrix(1, len, mxREAL);
    memcpy(mxGetPr(plhs[0]), arr, len*sizeof(double));
    if (nlhs > 1) {
        plhs[1] = mxCreateDoubleScalar(len);
    }

    // dellocate heap space
    free(arr);
}

MATLAB:

>> mex -largeArrayDims testarr.cpp
>> [a,n] = testarr
a =
     0    10    20    30    40
n =
     5
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top