1

Inspired from this post, I am interested to pass std::strings into the cell array. However, the mxDuplicateArray accepts mxArray format variables. I have tried to transform the std::string to mxArray with mxGetString but without success.

Could you please make a suggestion on this?

Thanks!

void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
    std::string str ("Hellooo"); 
    const char *cstr = str.c_str();
    mwSize len = 10;
    mxArray *mxarr = mxCreateCellMatrix(len, 1);
    mxArray *mxstr = mxCreateString("");
    mxGetString(mxstr, (char*) cstr, str.length());
    for(mwIndex i=0; i<len; i++) {
        // I simply replaced the call to mxDuplicateArray here
        mxSetCell(mxarr, i, mxDuplicateArray(mxstr));
    }
    mxDestroyArray(mxstr);
    plhs[0] = mxarr;
}
Community
  • 1
  • 1
Thoth
  • 993
  • 12
  • 36

2 Answers2

1

From the docs on mxGetString:

Call mxGetString to copy the character data of a string mxArray

What you want, is the opposite: create an mxArray from a c-style string. For that you can use mxCreateString directly. It seems to tried to use it to create an empty string at first. This should work:

void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
    std::string str ("Hellooo"); 
    const char *cstr = str.c_str();
    mwSize len = 10;
    mxArray *mxarr = mxCreateCellMatrix(len, 1);
    mxArray *mxstr = mxCreateString(cstr);
    // no need for this line
    // mxGetString(mxstr, (char*) cstr, str.length());
    for(mwIndex i=0; i<len; i++) {
        // I simply replaced the call to mxDuplicateArray here
        mxSetCell(mxarr, i, mxDuplicateArray(mxstr));
    }
    mxDestroyArray(mxstr);
    plhs[0] = mxarr;
}
sebastian
  • 9,526
  • 26
  • 54
1

You could also cut out the call to mxDuplicateArray (and mxDestroyArray).

#include "mex.h"
#include <string>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    std::string str("Hellooo"); 
    const char *cstr = str.c_str();
    mwSize len = 10;
    mxArray *mxarr = mxCreateCellMatrix(len, 1);
    for (mwIndex i=0; i<len; i++) {
        mxSetCell(mxarr, i, mxCreateString(cstr));
    }
    plhs[0] = mxarr;
}

Untested...

chappjc
  • 30,359
  • 6
  • 75
  • 132
  • @Thoth I think the MATLAB memory manager owns each string, but now that I look at the docs, ti says to use `mxDestroyArray`... – chappjc Nov 03 '14 at 19:38
  • @chappjc: actually your code is correct as is; cell-arrays (and structure fields) are supposed to "steal" ownership of pointers, so you shouldn't free an array assigned to a cell – Amro Nov 03 '14 at 19:44
  • @Amro Not suggesting to free the array assigned to the cell, just to ensure that MATLAB knows to free the `mxArray` when the cell is cleared (does the `mxArray` captured by the cell get handles by MATLAB garbage collection). Kind of like `mxFastZeros` creates an array that requries `mxCreateSharedDataCopy` to get a "managed" array. If needed (not sure), the way to do that is with `mxDuplicateArray` or maybe `mxCreateReference`. – chappjc Nov 03 '14 at 19:50
  • Just tested with enormous number and size of strings and it seems to release memory when the cell is cleared, so I guess it's OK. – chappjc Nov 03 '14 at 19:55
  • yes, cell and struct arrays are destroyed recursively, including the member cells and fields: http://www.mathworks.com/help/matlab/matlab_external/memory-management-issues.html#brfpzpx-1, hence no memory is leaked in the example above – Amro Nov 03 '14 at 20:06
  • @Amro Right, upon `clear` you can even watch the memory usage go down in the task manager as it cycles through each cell. It makes sense that when the cell gets each array, MATLAB will ensure each one is cleared when the cell itself cleared. I was a little uncertain since you can't just let the output of `mxCreateString` go undestroyed in a MEX file, but actually when the string joins a cell array it crosses into the managed MATLAB workspace. Nice exercise. – chappjc Nov 03 '14 at 20:12