How to use object arrays in MEX

Hello everybody!!
I would appreciate any help on my questions below.
I have simple user-defined class, which is actually a wrapper around MEX library. To support vectorized operations with objects of the class effectively I need to work with arrays of objects on C/C++ level in MEX. In relation with this I have several questions:
1. How can I create array of objects of the class inside MEX library?
2. How can I access each individual object of array of objects supplied by user to MEX-function.
I stuck on these issues and I would be grateful for any advice.
Class is NOT handle based, it looks like (bare minimum):
classdef abc
properties (SetAccess = public)
a
end % properties
function obj = abc(x)
if nargin == 0
obj.a = 0;
elseif nargin == 1
obj.a = x;
end
end % constructor
end % classdef

 Respuesta aceptada

James Tursa
James Tursa el 4 de Abr. de 2011

1 voto

You can do this with a helper m-file:
% CreateClassArray.m helper file for mxCreateClassArray mex function
function class_array = CreateClassArray(dims,classname)
estring = 'class_array(';
for k=1:numel(dims);
estring = [estring '1:' num2str(dims(k)) ','];
end
estring(end) = ')';
estring = [estring '=' classname ';'];
eval(estring);
end
And then you can use this function in your mex routine:
/* Create a class array with default class element entries */
mxArray *mxCreateClassArray(mwSize ndim, const mwSize *dims, const char *classname)
{
mxArray *rhs[2];
mxArray *mx, *mxtrap;
mwSize i;
double *pr;
rhs[0] = mxCreateDoubleMatrix(1, ndim, mxREAL);
pr = mxGetPr(rhs[0]);
for( i=0; i<ndim; i++ ) {
pr[i] = dims[i];
}
rhs[1] = mxCreateString(classname);
if( mxtrap = mexCallMATLABWithTrap(1,&mx,2,rhs,"CreateClassArray") ) {
mxDestroyArray(mxtrap);
mx = NULL;
}
mxDestroyArray(rhs[1]);
mxDestroyArray(rhs[0]);
return mx;
}
Caution: The above is bare bones with NO ARGUMENT CHECKING. I will clean this up with more comments and put in argument checking and post to the FEX in the near future. Also, the above assumes R2008b or later. For R2008a there is no mexCallMATLABWithTrap function in the API. In that case download the FEX submission noted below for mxGetPropertyPtr and there is a replacement mexCallMATLABWithTrap function included.
You might also be interested in this FEX submission for getting the mxArray pointers to class element properties:

Más respuestas (1)

Pavel Holoborodko
Pavel Holoborodko el 5 de Abr. de 2011

0 votos

Hi, James.
Thank you for your prompt and insightful answer. Actually I was hoping for answer from you :-). It is apparent that you are one of the MEX gurus around and I’ve been learning a lot from your posts relating to MEX development – thank you for your efforts helping others.
Additional thanks for drawing my attention to memory-wise inefficiency of mxGetProperty – it might hurt my MEX library too, since objects can be very large. Too many hacks needed for mixing new MATLAB OOP with MEX, don’t you think? Maybe it has sense to switch back to struct-based classes?

8 comentarios

James Tursa
James Tursa el 5 de Abr. de 2011
The cat's out of the bag for the new OOP stuff ... I just hope they keep supporting the old method as well. And if you think mxGetPropertyPtr was a hack, wait 'till you see what I had to do to get an mxPutPropertyPtr routine! Prototype seems to work OK, still in testing. Maybe ready to post in a week or two.
Pavel Holoborodko
Pavel Holoborodko el 7 de Abr. de 2011
I.
I've just tested passing objects with large property field (1MB) from MATLAB to MEX and back. As it turned out MATLAB spends the most time converting objects to mxArray structure even before entering MEX (calling mexFunction) - few seconds.
Time spent in subsequent mxGetProperty call is not noticeable at all - 0.00000 seconds.
I use 2010b and I suspect that MATLAB clones pointers to property without deep copying when you call mxGetProperty already (also see below).
II.
I've hacked dlls which comes with MATLAB (is it legal?) - it seems that they already implemented property getters/setters without deep copy. They call them: mxGetPropertyShared, mxSetPropertyShared.
To use them just add functions declarations and link MEX with export library libmx.lib:
extern mxArray* mxGetPropertyShared(const mxArray*, unsigned int, const char *);
extern void mxSetPropertyShared(mxArray*, unsigned int, const char *, const mxArray*);
extern "C" bool mxIsIdentical(const mxArray*,const mxArray*);
Could you check do these functions make deep copy or not by your methods?
mxIsIdentical is another hidden routine. It returns true for pointers initialized both with mxGetPropertyShared (or mxGetProperty).
III.
Also there are hundreds other interesting mex-related functions which are not available to user in documentation. E.g. they also have internal mxCreateClassArray() to create object arrays.
I can hack most of them, although it is pretty solid chunk of work.
And I am not sure what to do - to report Mathworks about serious security breach in MATLAB (which allowed me to see their internals) or just publish C header file with all internal functions which can be used.
James Tursa
James Tursa el 7 de Abr. de 2011
I.
Could you send me some details on passing the large property? I don't know what you mean by "converting objects to mxArray structure". All variables in MATLAB *are* mxArrays. There is nothing to convert as I understand it, and references to the original (or in some cases shared data copy to the original) are always passed to the mex routine in the prhs[]. And unless something has changed, the doc clearly implies that mxGetProperty returns a deep copy. Also, the test routines in my mxGetPropertyPtr FEX submission clearly show the deep copy behavior.
II & III.
Good info. I didn't know about the mxGetPropertyShared and mxSetPropertyShared. I will have to look into it and compare them to my version of mxSetPropertyPtr (which also sets a shared data copy). As for using these and other undocumented functions in mex code, I do it because I need to have efficient functions available to work in mex routines and TMW doesn't supply everything needed in the official API, particularly for the new classdef classes. To me this means my code may not work in future versions of MATLAB, but I am willing to accept that risk in exchange for the efficiency now. If it breaks in the future then I will tackle that problem then. (In fact, it might even be broken right now and I just don't know it because I haven't thrown the right test case at it to show it)
James Tursa
James Tursa el 8 de Abr. de 2011
Just a quick glance only showed C++ mangled names for mxGetPropertyShared etc on my WinXP 32-bit. Are you using C++? What system/compiler?
James Tursa
James Tursa el 9 de Abr. de 2011
Follow-up: I tested mxGetPropertyShared and it does indeed behave as expected, returning a shared data copy of the original property. Had to do it in C++ since there is no undecorated name in the lib for C to link with. Haven't had a chance to look at any of the others yet.
Pavel Holoborodko
Pavel Holoborodko el 11 de Abr. de 2011
I'm using Visual C++ 2010, so just placing "extern" in front of the functions declarations was enough (mangled names produced by VC++ 2010 coincide with ones produced by VC++ 2005 which was used for libmx.dll compilation).
Hidden functions (but mistakenly exported) are all mangled, public exported with extern "C" for compatibility.
Pavel Holoborodko
Pavel Holoborodko el 11 de Abr. de 2011
And sorry for late response.
Also I had no chance to prepare simple example since I found other issues in my MEX to be covered first - just to be sure to not make false statements.
Pavel Holoborodko
Pavel Holoborodko el 12 de Abr. de 2011
I've finished my tests with large property passing. I was wrong - it works fine, Matlab passes large property without delay. Sorry for
misleading you.
P.S.
Looking forward to see what 2011a is offering.

Iniciar sesión para comentar.

Categorías

Más información sobre Write C Functions Callable from MATLAB (MEX Files) en Centro de ayuda y File Exchange.

Etiquetas

Community Treasure Hunt

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

Start Hunting!

Translated by