How to access Matlab string() data in MEX/C?

24 views (last 30 days)
Hello,
I'm pretty new to Matlab, and I'm trying to write a MEX function that interfaces with a Matlab script that creates a lot of string array data. This is specifically "strings", not mxChar arrays.
However, I can't figure out how to access this string data after passing it to the MEX function. All of the relevant functions (mxGetChars, mxGetString, mxArrayToString, etc) seem to only work with mxChar arrays, and the more generic functions are unable to parse or even understand a string array object.
Are there any API calls I can use that haven't been documented yet, or will I just have to do a bunch of data manipulation before and after the MEX function call within Matlab itself? Passing everything through conversion functions like cellstr() kind of works, but seems like a lot of overhead. I also understand that using char arrays instead of strings for general use might be preferable, but I'm trying to change as little of the original Matlab code as possible.
A generic example of what I'm trying to parse:
stringarray = [string('one', string('two')];
mexTestFunction(stringarray);

Answers (2)

John
John on 29 Jun 2018
Edited: John on 29 Jun 2018
I'm dealing with the same issue. As a cleaner, but higher runtime cost alternative, you can make a Matlab call to convert the string to a char array. Here is an example of parsing a single Matlab string:
...
}else if( mxIsClass(pr, "string") ){
//Matlab's String class is encapsulated,
//use Matlab call to convert it to char array
mxArray *string_class[1], *char_array[1];
string_class[0] = pr;
mexCallMATLAB(1, char_array, 1, string_class, "char");
//Parse the char array to create an std::string
int buflen = mxGetN(char_array[0])*sizeof(mxChar)+1;
char* buf = new char[buflen];
mxGetString(char_array[0],buf,buflen);
data = std::string(buf);
delete buf;
}else{
...
That being said, making too many Matlab calls defeats the point of a MEX function, so I am going to look at hacking into the private string data field. Thanks for the info!
Edit: As long as Matlab's string implementation doesn't change, you can use:
}else if( mxIsClass(pr, "string") ){
mxArray* char_array = mxGetProperty(pr,0,"data");
int buflen = mxGetN(char_array)*sizeof(mxChar)+1;
char* buf = new char[buflen];
mxGetString(char_array,buf,buflen);
data = std::string(buf);
delete buf;
}else{
This will actually create a copy of the data property and the blog post Jim listed includes a workaround to directly access the property, but for small strings it's probably just as well to copy the data.
  2 Comments
Cris Luengo
Cris Luengo on 24 May 2021
I have been playing with this. Unfortunately, mxGetProperty doesn't work with private properties. It returns a NULL pointer. Calling back to MATLAB to convert using char or cellstr (for a string array with more than one string) is the best approach.
Antonio Javier Barragán Piña
Thanks! You saved me! It is an undesirable solution, but under the circumstances, it is better than nothing.

Sign in to comment.


James Tursa
James Tursa on 20 Mar 2017
Edited: James Tursa on 20 Mar 2017
I don't have a recent enough version of MATLAB & C compiler to check this, but I suspect that the string class is an OOP classdef object. You can check this by passing in a string variable to the following mex routine and checking the result:
#include "mex.h"
int mxIsOpaque(const mxArray *); /* Undocumented API function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if( nrhs ) {
plhs[0] = mxCreateDoubleScalar(mxIsOpaque(prhs[0]));
}
}
If the result is a 1, then the variable is opaque (i.e., a classdef object). Unfortunately, the only way to deal with these in a mex routine is through the mxGetProperty and mxPutProperty API functions. But these will only work for you if you know the property names and are allowed to access them. And even if you can get at the top level properties of a string object, the actual data you want to get at may be buried multiple levels down deep within the object, and you might have no hope of retrieving it in a mex routine. Good luck ...
  2 Comments
Jim Hokanson
Jim Hokanson on 23 Oct 2017
It seems like the format for mxIsOpaque returns a bool, not an int (for 2016b). I just commented that line out and the code works.
In terms of the result, I'm getting a 1 (is opaque).

Sign in to comment.

Categories

Find more on Characters and Strings in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!