diff --git a/.gitignore b/.gitignore index 3a1d936..811886c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ *~ .nfs* build/* +*.pyc +*.pyo + diff --git a/mltypes/__init__.py b/mltypes/__init__.py new file mode 100644 index 0000000..4cfc979 --- /dev/null +++ b/mltypes/__init__.py @@ -0,0 +1,20 @@ +from matlab import mx +import sys + +def _findtype(typelist): + for (modstr, clsstr) in typelist: + if len(modstr): + adjusted_modstr = "mltypes.%s" % modstr + else: + adjusted_modstr = "mltypes" + try: + tempmod = __import__(adjusted_modstr, globals(), locals(), [clsstr], 0) + cls = getattr(tempmod, clsstr); + return cls; + except: + pass + # if we got this far and found nothing, just use mx.Array + return mx.Array; + + +class cell(mx.Array): pass diff --git a/mro.m b/mro.m new file mode 100644 index 0000000..814beb2 --- /dev/null +++ b/mro.m @@ -0,0 +1,68 @@ +% mrolist = mro(object, addvirtual=true, autosplit=true) +% Determines something similar to the method resolution order for an object. +% Note that this is probably not the actual order, since a cursory inspection +% did not reveal any clues as to what the correct order might be. So this just +% produces a list of all of the object's classes from most to least specific. +% +% If addvirtual is true, a virtual class may be appended to the end of the +% mro list to indicate the nonexistent root of a particular hierarchy. +% The virtual classes are: +% _numeric: Numbers, logicals, and characters. +% _object: MATLAB objects +% _java: Java objects +% _com: COM objects (windows only) +% _interface: COM interface (windows only) +% +% Note that no attempt is made to enumerate the class hierarchy +% of Java classes. We could probably do that, but let's keep it simple for now. +function [mrolist] = mro(object,addvirtual,autosplit) +if nargin < 2, addvirtual = true; end +if nargin < 3, autosplit = true; end +classname = class(object); +mrolist = {classname}; +classqueue = {classname}; +while ~isempty(classqueue) + mco = meta.class.fromName(classqueue{1}); + classqueue = classqueue(2:end); + if isempty(mco) + % MATLAB doesn't abstract Java class reflection, + % so it will return an empty metaclass handle. + continue; + end + supers = mco.SuperClasses; + for i=1:numel(supers) + name = supers{i}.Name; + if ~ismember(name, mrolist) + mrolist = [mrolist name]; %#ok + classqueue = [classqueue name]; %#ok + end + end +end + +if addvirtual + if isnumeric(object) || ischar(object) || islogical(object) + mrolist{end+1} = '_numeric'; + elseif isobject(object) + mrolist{end+1} = '_object'; + elseif isjava(object) + mrolist{end+1} = '_java'; + % In case this gets used on Windows... + elseif iscom(object) + mrolist{end+1} = '_com'; + elseif isinterface(object) + mrolist{end+1} = '_interface'; + end +end + +if autosplit + for i=1:numel(mrolist) + classname = mrolist{i}; + dots = strfind(classname, '.'); + if isempty(dots) + mrolist{i} = {'', classname}; + else + d = dots(end); + mrolist{i} = {classname(1:d-1), classname(d+1:end)}; + end + end +end diff --git a/pymex.h b/pymex.h index 36a7995..38e049e 100644 --- a/pymex.h +++ b/pymex.h @@ -79,6 +79,7 @@ bool mxIsPyObject(const mxArray* mxobj); mxArray* PyObject_to_mxLogical(PyObject* pyobj); PyObject* mxChar_to_PyBytes(const mxArray* mxchar); PyObject* mxCell_to_PyTuple(const mxArray* mxobj); +PyObject* mxCell_to_PyTuple_recursive(const mxArray* mxobj); mxArray* PyBytes_to_mxChar(PyObject* pystr); mxArray* PyObject_to_mxChar(PyObject* pyobj); mxArray* PySequence_to_mxCell(PyObject* pyobj); @@ -87,6 +88,7 @@ mxArray* PyObject_to_mxLong(PyObject* pyobj); PyObject* Any_mxArray_to_PyObject(const mxArray* mxobj); mxArray* Any_PyObject_to_mxArray(PyObject* pyobj); bool PyMXObj_Check(PyObject* pyobj); +PyObject* Calculate_matlab_mro(mxArray* mxobj); PyObject* Py_mxArray_New(mxArray* mxobj, bool duplicate); int Py_mxArray_Check(PyObject* pyobj); PyObject* mxArray_to_PyArray(const mxArray* mxobj, bool duplicate); diff --git a/sharedfuncs.c b/sharedfuncs.c index c89d75a..7977416 100644 --- a/sharedfuncs.c +++ b/sharedfuncs.c @@ -252,6 +252,23 @@ PyObject* mxCell_to_PyTuple(const mxArray* mxobj) { } return pyobj; } + +PyObject* mxCell_to_PyTuple_recursive(const mxArray* mxobj) { + mwSize numel = mxGetNumberOfElements(mxobj); + PyObject* pyobj = PyTuple_New(numel); + mwSize i; + for (i=0; i