Should have been simple to read a class instance from .mat via C++, but wasn't
Ältere Kommentare anzeigen

Hello:
I'm looking to write a class instance via Matlab and read it back from a C++ program. Writing the file from Matlab, opening it in C++, and identifying the type of class all work for me. Reading the class properties does not work.
The screenshot says it all:
In Matlab (editor and command window shown at far left):
- I defined a class simple with three scalar properties
- I instantiated the class and wrote it to file
In VS2013 (source editor at center right, debugger console window at top right):
- I opened the file via C++ console application using matOpen (not visible in the source editor, but did succeed)
- I called matGetDir to enumerate the variable names
- I looped over the variables, calling matGetVariable on each one
- I checked the name to confirm that we found an instance of "simple", visible in the DOS window at upper right in the screenshot
- I find zero elements, zero fields, and 2 dimensions. This doesn't sound good.
- mxIsClass verifies that the mxArray holds an instance of simple.
- mxIsEmpty returns true. This doesn't sound good either.
- I start looking for properties via mxGetProperty, checking variants that might work. None are found.
Somewhere here I've got a fundamental misconception. Does anyone have a suggestion?
Many thanks
Matthew
Akzeptierte Antwort
Weitere Antworten (10)
Can't see any error in your code.
Perhaps you could make one change. Try using matGetNextVariable(), instead of matGetVariable().
Also I notice you are stopped in the debugger. Did you check the value of "num"? Is it 1 or greater than than 1.
1 Kommentar
Matthew Britton
am 27 Okt. 2014
OK, you are the victim of indifferent documentation.
If you check the example matdgns.c file in your matlab installation in:
[MATLAB]\extern\examples\eng_mat
You will find the required gem of information:
/*
* get directory of MAT-file
*/
dir = (const char **)matGetDir(pmat, &ndir);
if (dir == NULL) {
printf("Error reading directory of file %s\n", file);
return(1);
} else {
printf("Directory of %s:\n", file);
for (i=0; i < ndir; i++)
printf("%s\n",dir[i]);
}
mxFree(dir);
/* In order to use matGetNextXXX correctly, reopen file to read in headers. */
if (matClose(pmat) != 0) {
printf("Error closing file %s\n",file);
return(1);
}
pmat = matOpen(file, "r");
if (pmat == NULL) {
printf("Error reopening file %s\n", file);
return(1);
}
So after using matGetDir() you have to close the file and reopen it in order to read the variables from the file. Presumably the read pointer is in the wrong place after matGetDir().
Regards.
Matthew Britton
am 27 Okt. 2014
0 Stimmen
The following works on my system (matlab 2014a) compiled with VS 2013. All error checking omitted to avoid excess typing.
In ReadMatFile.cpp
#include "mex.h"
#include "mat.h"
void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
const char* pmatfilename = mxArrayToString(prhs[0]);
MATFile* mfp = matOpen(pmatfilename, "r");
int numvars = 0;
char** pmatfileinfo = matGetDir(mfp, &numvars); //Dummy to test open/close
matClose(mfp);
mfp = matOpen(pmatfilename, "r");
const char* name = 0;
mxArray* pa = matGetNextVariable(mfp, &name);
const mxArray* pProp = 0;
const char* pStr = 0;
while (pa != NULL)
{
mexPrintf(name);
pProp = mxGetProperty(pa, 0, "prop_1");
pStr = mxArrayToString(pProp);
mexPrintf(pStr);
pProp = mxGetProperty(pa, 0, "prop_2");
pStr = mxArrayToString(pProp);
mexPrintf(pStr);
mxDestroyArray(pa);
pa = matGetNextVariable(mfp, &name);
}
mxFree(pmatfileinfo);
matClose(mfp);
}
Better to copy and paste your code into the text box rather than provide a screenshot otherwise it is a pain to type it all out.
The matlab class was:
classdef Test
properties
prop_1;
prop_2;
end
methods (Access = 'public')
function This = Test(p1, p2)
This.prop_1 = p1;
This.prop_2 = p2;
end
end
end
>> txx = Test('12345', 'sdfadfdf');
>> save('test.mat', 'txx');
>> mex ReadMatFile.cpp
>> ReadMatFile('test.mat');
txx12345sdfadfdf
2 Kommentare
James Tursa
am 28 Okt. 2014
Does this work from a cold start? I.e., start MATLAB and then run the mex routine ReadMatFile immediately without calling Test first?
SK
am 28 Okt. 2014
Yes, works fine on cold start.
Regards.
Matthew Britton
am 27 Okt. 2014
0 Stimmen
1 Kommentar
Should work. I've compiled dll's (mexw64's) using VS. The only issue is how to pass in Matlab data which is done via mexFunction. But in your case I assume you are not passing in any data from Matlab so as far as I know there is no need for a mexFunction. Are you linking in the correct matlab libraries
[MATLAB}extern\lib\win32\microsoft\
or [MATLAB}extern\lib\win64\microsoft\
as per your system.
Another thing you could try is use:
mex -v ReadMatFile.cpp
which produces verbose output from mex. This will tell you the visual C++ compiler options that mex is using. Make sure that your VS compiler options are compatible. [You dont need /export:mexFunction in the linker flags and also don't need the MATLAB_MEX_FILE preprocessor definition and the target will be .exe rather than mexw64.]
Matthew Britton
am 28 Okt. 2014
Actually, I have only used the mex and mx API in the dll not the matXXX API. I'll test your code out later, but one thing I noticed in the diary file:
COMPFLAGS : /Zp8
Now 8 byte packing is the default for the microsoft compiler according to the Docs but perhaps you could try adding that flag explicity. Also try adding the MX_COMPAT_32 preprocessor flag which is present in the diary file:
/DMX_COMPAT_32
Matthew Britton
am 28 Okt. 2014
0 Stimmen
"The MAT-File Interface Library does not support MATLAB objects created by user-defined classes."
So officially reading user defined objects is not supported. Perhaps it worked with mex by fluke. Maybe you can check this Library that avoids the mat-File API altogether and relies on the published mat file format.
SK
am 28 Okt. 2014
0 Stimmen
I guess one has to learn the hard way sometimes - but you always end up learning something - so the effort is not entirely wasted. Perhaps you could mark the above as an answer. It may help some poor fellow who has the same problem.
Good luck.
Regards.
Kategorien
Mehr zu Write C Functions Callable from MATLAB (MEX Files) finden Sie in Hilfe-Center und File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!





