From af98d6870d8492729865b98b0334c253e94229db Mon Sep 17 00:00:00 2001 From: "U-muffy\\kwatford" Date: Sat, 5 Dec 2009 10:36:14 -0500 Subject: [PATCH 01/21] Woohoo, got it to compile in windows with gcc --- COMPILING_WINDOWS.md | 30 ++++++++++++++++++++++++++++++ Makefile | 19 +++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) create mode 100755 COMPILING_WINDOWS.md diff --git a/COMPILING_WINDOWS.md b/COMPILING_WINDOWS.md new file mode 100755 index 0000000..dd7ca70 --- /dev/null +++ b/COMPILING_WINDOWS.md @@ -0,0 +1,30 @@ +# Compiling for Windows # + +This is how I managed to compile pymex in Windows. There's probably +a better way, but I try not to use Windows that much myself. Maybe +I'll try one of Microsoft's compilers later, but MATLAB's lcc doesn't +seem to like Python's headers. + +You will need: +1. [cygwin](http://www.cygwin.com/) +2. [MinGW](http://www.mingw.org/) +3. Python 2.6 for Windows (not just the cygwin version) +4. [gnumex](http://gnumex.sourceforge.net/) + +Tell gnumex where both cygwin and MinGW are, but configure it for a MinGW build. +If you haven't already, check out pymex and make sure you're on the win32 branch +(the Makefile is different). If you don't have git already, consider using your +cygwin installer to get it, otherwise just make sure to get the right archive +from GitHub. + +Now, in Cygwin's bash, travel to the pymex directory and run `make`. If your Python26 +directory is somewhere other than C:\Python26, you'll need to tell make about it: +`make PYDIR=D:/MyStuff/Python26`. Use normal slashes, not backslashes. + +# Notes # + +Why mingw *and* cygwin? +Cygwin has useful tools like `make` and `git`, but for some reason gnumex does not +produce an appropriate set of mex options for cygwin's gcc (at least for me). +Compiling with MinGW and the standard Python for Windows also avoids depdendence on +Cygwin. The compiled mexw32 or mexw64 file should only require Python to work. \ No newline at end of file diff --git a/Makefile b/Makefile index 64d6fdd..11e8e57 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,6 @@ -PYTHON ?= python2.6 -MATLAB_SCRIPT ?= matlab -TMW_ROOT ?= $(shell ${MATLAB_SCRIPT} -e | grep MATLAB= | sed s/^MATLAB=//) - -CFLAGS=$(shell ${PYTHON}-config --cflags) -CLIBS=$(shell ${PYTHON}-config --libs) -LDFLAGS=$(shell ${PYTHON}-config --ldflags) -L$(shell ${PYTHON}-config --prefix)/lib +PYDIR ?= C:/Python26 +CFLAGS= -I$(shell cygpath -m ${PYDIR}/include) +CLIBS= $(shell cygpath -m ${PYDIR}/libs/libpython26.a) BUILDBRANCH = $(shell git branch --no-color | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/') ifeq ($(BUILDBRANCH),) @@ -16,23 +12,22 @@ ifeq ($(BUILDTAG),) endif BUILDNAME = $(BUILDBRANCH)/$(BUILDTAG) -MEXEXT ?= $(shell ${TMW_ROOT}/bin/mexext) +MEXEXT ?= $(shell mexext.bat) DEBUG ?= $(if $(wildcard .debug_1),1,0) TARGET = pymex.${MEXEXT} MEXFLAGS ?= -MEXENV = CFLAGS="\$$CFLAGS ${CFLAGS}" CLIBS="\$$CLIBS ${CLIBS}" LDFLAGS="\$$LDFLAGS ${LDFLAGS}" -MEX = ${TMW_ROOT}/bin/mex +MEX = mex.bat all: ${TARGET} ${TARGET}: pymex.c sharedfuncs.c commands.c *module.c pymex.h .debug_${DEBUG} @echo building $(BUILDNAME) - $(MEX) $(MEXFLAGS) $(MEXENV) \ + $(MEX) $(MEXFLAGS) $(CFLAGS) \ -DPYMEX_DEBUG_FLAG=$(DEBUG) \ -DPYMEX_BUILD="$(BUILDNAME)" \ - pymex.c sharedfuncs.c *module.c + pymex.c sharedfuncs.c *module.c $(CLIBS) .debug_0: @echo "Debug disabled." From ba41b3759479b81a4213a63f107ffaec844df0f8 Mon Sep 17 00:00:00 2001 From: kw Date: Sat, 5 Dec 2009 08:58:18 -0700 Subject: [PATCH 02/21] markdown formatting issue --- COMPILING_WINDOWS.md | 59 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 29 deletions(-) mode change 100755 => 100644 COMPILING_WINDOWS.md diff --git a/COMPILING_WINDOWS.md b/COMPILING_WINDOWS.md old mode 100755 new mode 100644 index dd7ca70..556b5f7 --- a/COMPILING_WINDOWS.md +++ b/COMPILING_WINDOWS.md @@ -1,30 +1,31 @@ -# Compiling for Windows # - -This is how I managed to compile pymex in Windows. There's probably -a better way, but I try not to use Windows that much myself. Maybe -I'll try one of Microsoft's compilers later, but MATLAB's lcc doesn't -seem to like Python's headers. - -You will need: -1. [cygwin](http://www.cygwin.com/) -2. [MinGW](http://www.mingw.org/) -3. Python 2.6 for Windows (not just the cygwin version) -4. [gnumex](http://gnumex.sourceforge.net/) - -Tell gnumex where both cygwin and MinGW are, but configure it for a MinGW build. -If you haven't already, check out pymex and make sure you're on the win32 branch -(the Makefile is different). If you don't have git already, consider using your -cygwin installer to get it, otherwise just make sure to get the right archive -from GitHub. - -Now, in Cygwin's bash, travel to the pymex directory and run `make`. If your Python26 -directory is somewhere other than C:\Python26, you'll need to tell make about it: -`make PYDIR=D:/MyStuff/Python26`. Use normal slashes, not backslashes. - -# Notes # - -Why mingw *and* cygwin? -Cygwin has useful tools like `make` and `git`, but for some reason gnumex does not -produce an appropriate set of mex options for cygwin's gcc (at least for me). -Compiling with MinGW and the standard Python for Windows also avoids depdendence on +# Compiling for Windows # + +This is how I managed to compile pymex in Windows. There's probably +a better way, but I try not to use Windows that much myself. Maybe +I'll try one of Microsoft's compilers later, but MATLAB's lcc doesn't +seem to like Python's headers. + +You will need: + +1. [cygwin](http://www.cygwin.com/) +2. [MinGW](http://www.mingw.org/) +3. Python 2.6 for Windows (not just the cygwin version) +4. [gnumex](http://gnumex.sourceforge.net/) + +Tell gnumex where both cygwin and MinGW are, but configure it for a MinGW build. +If you haven't already, check out pymex and make sure you're on the win32 branch +(the Makefile is different). If you don't have git already, consider using your +cygwin installer to get it, otherwise just make sure to get the right archive +from GitHub. + +Now, in Cygwin's bash, travel to the pymex directory and run `make`. If your Python26 +directory is somewhere other than C:\Python26, you'll need to tell make about it: +`make PYDIR=D:/MyStuff/Python26`. Use normal slashes, not backslashes. + +# Notes # + +Why mingw *and* cygwin? +Cygwin has useful tools like `make` and `git`, but for some reason gnumex does not +produce an appropriate set of mex options for cygwin's gcc (at least for me). +Compiling with MinGW and the standard Python for Windows also avoids depdendence on Cygwin. The compiled mexw32 or mexw64 file should only require Python to work. \ No newline at end of file From a938e639e3cde20250eace8576321a16abb99323 Mon Sep 17 00:00:00 2001 From: kw Date: Sat, 5 Dec 2009 16:50:30 -0700 Subject: [PATCH 03/21] Adding notes about win32 binary download --- COMPILING_WINDOWS.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/COMPILING_WINDOWS.md b/COMPILING_WINDOWS.md index 556b5f7..956b910 100644 --- a/COMPILING_WINDOWS.md +++ b/COMPILING_WINDOWS.md @@ -28,4 +28,16 @@ Why mingw *and* cygwin? Cygwin has useful tools like `make` and `git`, but for some reason gnumex does not produce an appropriate set of mex options for cygwin's gcc (at least for me). Compiling with MinGW and the standard Python for Windows also avoids depdendence on -Cygwin. The compiled mexw32 or mexw64 file should only require Python to work. \ No newline at end of file +Cygwin. The compiled mexw32 or mexw64 file should only require Python to work. +Of course, if you have installed the right msys ports you can probably do without cygwin. + +# Binaries # + +If MATLAB's `mexext` command tells you `mexw32`, then you may be able to skip the compilation +and just drop [pymex.mexw32](http://cloud.github.com/downloads/kw/pymex/pymex.mexw32) into your +pymex directory. You do still need the pymex distribution and to have Python 2.6 installed. There +is currently no difference between this and the master branch other than compilation, so it shouldn't +matter which branch you have out. Note that this binary was compiled under MATLAB 2008b in Windows 7 +with MinGW's gcc. I have no idea whether it will work on other configurations. + +There is presently no `mexw64` binary available. Sorry. \ No newline at end of file From b30056637a1ef98aeca9bfbdf5021bccf64ed6a0 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 11:05:19 +0100 Subject: [PATCH 04/21] rename .c to .cpp for visual studio --- engmodule.c => engmodule.cpp | 0 matmodule.c => matmodule.cpp | 0 mexmodule.c => mexmodule.cpp | 0 mxmodule.c => mxmodule.cpp | 0 pymex.c => pymex.cpp | 0 sharedfuncs.c => sharedfuncs.cpp | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename engmodule.c => engmodule.cpp (100%) rename matmodule.c => matmodule.cpp (100%) rename mexmodule.c => mexmodule.cpp (100%) rename mxmodule.c => mxmodule.cpp (100%) rename pymex.c => pymex.cpp (100%) rename sharedfuncs.c => sharedfuncs.cpp (100%) diff --git a/engmodule.c b/engmodule.cpp similarity index 100% rename from engmodule.c rename to engmodule.cpp diff --git a/matmodule.c b/matmodule.cpp similarity index 100% rename from matmodule.c rename to matmodule.cpp diff --git a/mexmodule.c b/mexmodule.cpp similarity index 100% rename from mexmodule.c rename to mexmodule.cpp diff --git a/mxmodule.c b/mxmodule.cpp similarity index 100% rename from mxmodule.c rename to mxmodule.cpp diff --git a/pymex.c b/pymex.cpp similarity index 100% rename from pymex.c rename to pymex.cpp diff --git a/sharedfuncs.c b/sharedfuncs.cpp similarity index 100% rename from sharedfuncs.c rename to sharedfuncs.cpp From 58c2bb197273340657b5c03a2de0abac0cacf594 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 11:06:20 +0100 Subject: [PATCH 05/21] vs compatible vararg macro --- pymex.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pymex.h b/pymex.h index 4ac4b26..942400c 100644 --- a/pymex.h +++ b/pymex.h @@ -33,9 +33,9 @@ #endif #if PYMEX_DEBUG_FLAG -#define PYMEX_DEBUG(format, args...) mexPrintf(format,##args) +#define PYMEX_DEBUG(format, ...) mexPrintf(format,__VAR_ARGS__) #else -#define PYMEX_DEBUG(format, args...) /*nop*/ +#define PYMEX_DEBUG(format, ...) /*nop*/ #endif mxArray *box(PyObject *pyobj); From f29db438bf20f13a3fb2d7049873dfd438ff8ed5 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 11:13:57 +0100 Subject: [PATCH 06/21] move preprocessor if out of macro (not expanded by visual studio) --- commands.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) mode change 100644 => 100755 commands.c diff --git a/commands.c b/commands.c old mode 100644 new mode 100755 index aed8da5..fae7127 --- a/commands.c +++ b/commands.c @@ -184,6 +184,7 @@ PYMEX(TO_PYOBJECT, 1,1, plhs[0] = box(Any_mxArray_to_PyObject(prhs[0])); }) +#if PYMEX_DEBUG_FLAG PYMEX(CALL, 2,3, "Calls a callable python object. In addition to the " "object itself, the second argument is a cell array or tuple " @@ -223,6 +224,33 @@ PYMEX(CALL, 2,3, PyObject *result = PyObject_Call(callobj, args, kwargs); plhs[0] = box(result); }) +#else +PYMEX(CALL, 2,3, + "Calls a callable python object. In addition to the " + "object itself, the second argument is a cell array or tuple " + "of arguments. An optional third argument is a dict of keyword arguments. " + "No output unpacking is done. The standard object wrapper class implements that.", + { + PyObject *callobj = unbox(prhs[0]); + if (!PyCallable_Check(callobj)) + mexErrMsgIdAndTxt("python:NotCallable", "tried to call object which is not callable."); + PyObject *args = NULL; + if (mxIsCell(prhs[1])) + args = mxCell_to_PyTuple(prhs[1]); + else + args = unbox(prhs[1]); + if (!args || !PyTuple_Check(args)) + mexErrMsgIdAndTxt("python:NotTuple", "args must be a tuple"); + PyObject *kwargs = NULL; + if (nrhs > 2) { + kwargs = unbox(prhs[2]); + if (kwargs && !PyDict_Check(kwargs)) + mexErrMsgIdAndTxt("python:NoKWargs", "kwargs must be a dict or null"); + } + PyObject *result = PyObject_Call(callobj, args, kwargs); + plhs[0] = box(result); + }) +#endif PYMEX(IS_CALLABLE, 1,1, "Tests the object to see if it is callable.", From 37f7a6783b1b577e43e8774764070aca5b33d1c1 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 11:14:58 +0100 Subject: [PATCH 07/21] explicit enum cast required for vs --- pymex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pymex.cpp b/pymex.cpp index 939d2f4..49d8ae5 100644 --- a/pymex.cpp +++ b/pymex.cpp @@ -90,7 +90,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { } } else if (mxIsNumeric(prhs[0])) { - enum PYMEX_COMMAND cmd = (int) mxGetScalar(prhs[0]); + enum PYMEX_COMMAND cmd = (PYMEX_COMMAND) (int) mxGetScalar(prhs[0]); /* While the numeric command selector is no longer used for various reasons, I have left it in since it is faster than the string-based command selector and From d4d13009ac6b921f01a170dcc5da7070f254859d Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 11:23:50 +0100 Subject: [PATCH 08/21] explicit conversion for void * to void ** --- sharedfuncs.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/sharedfuncs.cpp b/sharedfuncs.cpp index 2ab791d..ddea8ae 100644 --- a/sharedfuncs.cpp +++ b/sharedfuncs.cpp @@ -125,7 +125,8 @@ mxArray *box (PyObject *pyobj) { if (!boxed) return NULL; if (pyobj) mexLock(); mxArray *ptr_field = mxGetProperty(boxed, 0, "pointer"); - void **ptr = mxGetData(ptr_field); + void *ptr_one = mxGetData(ptr_field); + void **ptr = &ptr_one; *ptr = (void*) pyobj; mxSetProperty(boxed, 0, "pointer", ptr_field); return boxed; @@ -145,7 +146,8 @@ PyObject *unbox (const mxArray *mxobj) { return PyErr_Format(MATLABError, "Unboxed pointer is null."); } else { - void **ptr = mxGetData(mxGetProperty(mxobj, 0, "pointer")); + void *ptr_one = mxGetData(mxGetProperty(mxobj, 0, "pointer")); + void **ptr = &ptr_one; return (PyObject *) *ptr; } } @@ -168,7 +170,8 @@ PyObject *unboxn (const mxArray *mxobj) { it does not check this before doing the mxGetProperty */ bool mxIsPyNull (const mxArray *mxobj) { - void **ptr = mxGetData(mxGetProperty(mxobj, 0, "pointer")); + void *ptr_one = mxGetData(mxGetProperty(mxobj, 0, "pointer")); + void **ptr = &ptr_one; return !*ptr; } From 8e681b49967b1f2ed02dc729f5c998486c5661ea Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 12:13:28 +0100 Subject: [PATCH 09/21] dynamic arrays for visual studio (used c++ dynamic arrays as it seemed the easiest fix --- mexmodule.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) mode change 100644 => 100755 mexmodule.cpp diff --git a/mexmodule.cpp b/mexmodule.cpp old mode 100644 new mode 100755 index 77488f2..baa5ded --- a/mexmodule.cpp +++ b/mexmodule.cpp @@ -82,18 +82,23 @@ static PyObject *m_call(PyObject *self, PyObject *args, PyObject *kwargs) { return NULL; Py_DECREF(fakeargs); int nargin = PySequence_Size(args); - mxArray *inargs[nargin]; + mxArray **inargs; + inargs = new mxArray*[nargin]; int i; for (i=0; i= 0; if (nargout < 0) nargout = 1; - mxArray *outargs[nargout]; + mxArray **outargs; + outargs = new mxArray*[nargout]; mxArray *err = mexCallMATLABWithTrap(nargout, outargs, nargin, inargs, "feval"); - if (err) + if (err) { + delete [] outargs; return _raiselasterror(NULL); + } else { if (tupleout) { PyObject *outseq = PyTuple_New(nargout); @@ -104,12 +109,16 @@ static PyObject *m_call(PyObject *self, PyObject *args, PyObject *kwargs) { : mxArrayPtr_New(outargs[i]) ); } + delete [] outargs; return outseq; } - else + else { + mxArray *outzero = outargs[0]; + delete [] outargs; return wrap - ? Any_mxArray_to_PyObject(outargs[0]) - : mxArrayPtr_New(outargs[0]); + ? Any_mxArray_to_PyObject(outzero) + : mxArrayPtr_New(outzero); + } } } From 14e15f1fae1932b68711322788853ee0ffb6d0a8 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 12:13:59 +0100 Subject: [PATCH 10/21] unexpanded preprocessor definitions - dont seem essential in this case --- mexmodule.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mexmodule.cpp b/mexmodule.cpp index baa5ded..82ab83b 100755 --- a/mexmodule.cpp +++ b/mexmodule.cpp @@ -142,11 +142,7 @@ static PyMethodDef mex_methods[] = { #endif PyMODINIT_FUNC initmexmodule(void) { PyObject *m = Py_InitModule3("mex", mex_methods, - #if MATLAB_MEX_FILE - "MATLAB Extension API module" - #else "MATLAB Extension API module (only available inside MATLAB)" - #endif ); if (!m) return; From c2990b6d9aa3e303ecf3425782c8bd13a393a008 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 12:26:02 +0100 Subject: [PATCH 11/21] change import to include... not sure if this will require tighter #ifndefs etc. in headers --- mxmodule.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100644 => 100755 mxmodule.cpp diff --git a/mxmodule.cpp b/mxmodule.cpp old mode 100644 new mode 100755 index 52d0afe..3623d5b --- a/mxmodule.cpp +++ b/mxmodule.cpp @@ -2,8 +2,8 @@ For full license details, see the LICENSE file. */ #define MXMODULE -#import "pymex.h" -#import "structmember.h" +#include "pymex.h" +#include "structmember.h" static PyObject *dowrap(PyObject *cobj) { PyObject *nargs = PyTuple_New(0); From 394cf2e6e8c6c5efbc779eee1803b2ef07fd003c Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 12:39:43 +0100 Subject: [PATCH 12/21] dynamically allocate dims --- mxmodule.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mxmodule.cpp b/mxmodule.cpp index 3623d5b..e6c5750 100755 --- a/mxmodule.cpp +++ b/mxmodule.cpp @@ -21,7 +21,8 @@ static PyObject *dowrap(PyObject *cobj) { #define DIMS_FROM_SEQ(A) \ mwSize ndim = PySequence_Size(A); \ - mwSize dims[ndim]; \ + mwSize *dims; \ + dims = new mwSize[ndim]; \ mwSize i; \ for (i=0; i < ndim; i++) { \ PyObject *item = PySequence_GetItem(A, i); \ @@ -50,6 +51,7 @@ static PyObject *CreateCellArray(PyObject *self, PyObject *args, PyObject *kw) { DIMS_FROM_SEQ(pydims); Py_DECREF(pydims); mxArray *cell = mxCreateCellArray(ndim, dims); + delete [] dims; if (wrap) return dowrap(mxArrayPtr_New(cell)); else @@ -70,6 +72,7 @@ static PyObject *CreateNumericArray(PyObject *self, PyObject *args, PyObject *kw DIMS_FROM_SEQ(pydims); Py_DECREF(pydims); mxArray *array = mxCreateNumericArray(ndim, dims, class, complexity); + delete [] dims; if (wrap) return dowrap(mxArrayPtr_New(array)); else @@ -88,6 +91,7 @@ static PyObject *CreateStructArray(PyObject *self, PyObject *args, PyObject *kw) DIMS_FROM_SEQ(pydims); Py_DECREF(pydims); mxArray *array = mxCreateStructArray(ndim, dims, 0, NULL); + delete [] dims; if (wrap) return dowrap(mxArrayPtr_New(array)); else @@ -106,6 +110,7 @@ static PyObject *CreateCharArray(PyObject *self, PyObject *args, PyObject *kw) { DIMS_FROM_SEQ(pydims); Py_DECREF(pydims); mxArray *array = mxCreateCharArray(ndim, dims); + delete [] dims; if (wrap) return dowrap(mxArrayPtr_New(array)); else From fa721b73287af61162a7e324cb14a22848a241e6 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 12:40:40 +0100 Subject: [PATCH 13/21] renamce class variable (c++ keyword) --- mxmodule.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/mxmodule.cpp b/mxmodule.cpp index e6c5750..7c9eb25 100755 --- a/mxmodule.cpp +++ b/mxmodule.cpp @@ -61,17 +61,17 @@ static PyObject *CreateCellArray(PyObject *self, PyObject *args, PyObject *kw) { static PyObject *CreateNumericArray(PyObject *self, PyObject *args, PyObject *kw) { static char *kwlist[] = {"dims", "mxclass", "complexity", "wrap", NULL}; PyObject *pydims = NULL; - mxClassID class = mxDOUBLE_CLASS; + mxClassID class_id = mxDOUBLE_CLASS; mxComplexity complexity = mxREAL; int wrap = 0; if (!PyArg_ParseTupleAndKeywords(args, kw, "|Oiii", kwlist, - &pydims, &class, &complexity, &wrap)) + &pydims, &class_id, &complexity, &wrap)) return NULL; if (!pydims) pydims = PyTuple_New(0); else Py_INCREF(pydims); DIMS_FROM_SEQ(pydims); Py_DECREF(pydims); - mxArray *array = mxCreateNumericArray(ndim, dims, class, complexity); + mxArray *array = mxCreateNumericArray(ndim, dims, class_id, complexity); delete [] dims; if (wrap) return dowrap(mxArrayPtr_New(array)); @@ -230,8 +230,8 @@ static PyObject *mxArray_mxGetClassID(PyObject *self) { } static PyObject *mxArray_mxGetClassName(PyObject *self) { - const char *class = mxGetClassName(mxArrayPtr(self)); - return PyBytes_FromString(class); + const char *class_id = mxGetClassName(mxArrayPtr(self)); + return PyBytes_FromString(class_id); } static PyObject *mxArray_mxCalcSingleSubscript(PyObject *self, PyObject *args) { From 2d9b8c5458ed8101a40077f1cb5e13de7d736f05 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 12:44:10 +0100 Subject: [PATCH 14/21] another array allocation (subs) --- mxmodule.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mxmodule.cpp b/mxmodule.cpp index 7c9eb25..640e7f1 100755 --- a/mxmodule.cpp +++ b/mxmodule.cpp @@ -243,14 +243,17 @@ static PyObject *mxArray_mxCalcSingleSubscript(PyObject *self, PyObject *args) { "Can't calculate %ld-dimensional subscripts for %ld-dimensional array", (long) len, (long) dims); } - mwIndex subs[len]; + mwIndex *subs; + subs = new mwIndex[len]; mwIndex i; for (i=0; i Date: Fri, 2 Jul 2010 15:43:09 +0100 Subject: [PATCH 15/21] basic matlab make file --- makeall.m | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100755 makeall.m diff --git a/makeall.m b/makeall.m new file mode 100755 index 0000000..7be0b6e --- /dev/null +++ b/makeall.m @@ -0,0 +1,11 @@ + + +%mex -IC:\Python26\include pymex.cpp +%mex -IC:\Python26\include sharedfuncs.cpp +% mex -IC:\Python26\include engmodule.cpp +% mex -IC:\Python26\include mexmodule.cpp +%mex -IC:\Python26\include mxmodule.cpp +%mex -IC:\Python26\include matmodule.cpp + + +mex -v -IC:\Python26\include pymex.cpp sharedfuncs.cpp engmodule.cpp matmodule.cpp mexmodule.cpp mxmodule.cpp C:\Python26\libs\python26.lib From 6591d3169551f52f19364eec5d9b36087cf0ddc3 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 23:15:56 +0100 Subject: [PATCH 16/21] mistake here - deleted inargs too soon --- mexmodule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mexmodule.cpp b/mexmodule.cpp index 82ab83b..e78bf49 100755 --- a/mexmodule.cpp +++ b/mexmodule.cpp @@ -88,13 +88,13 @@ static PyObject *m_call(PyObject *self, PyObject *args, PyObject *kwargs) { for (i=0; i= 0; if (nargout < 0) nargout = 1; mxArray **outargs; outargs = new mxArray*[nargout]; mxArray *err = mexCallMATLABWithTrap(nargout, outargs, nargin, inargs, "feval"); + delete [] inargs; if (err) { delete [] outargs; return _raiselasterror(NULL); From e8988394befdcd49542c5a176a085390d7ba464e Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Fri, 2 Jul 2010 23:43:00 +0100 Subject: [PATCH 17/21] messed up box/unbox with dereferencing when all that was needed was an explicit cast to void ** --- sharedfuncs.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) mode change 100644 => 100755 sharedfuncs.cpp diff --git a/sharedfuncs.cpp b/sharedfuncs.cpp old mode 100644 new mode 100755 index ddea8ae..f980141 --- a/sharedfuncs.cpp +++ b/sharedfuncs.cpp @@ -125,8 +125,7 @@ mxArray *box (PyObject *pyobj) { if (!boxed) return NULL; if (pyobj) mexLock(); mxArray *ptr_field = mxGetProperty(boxed, 0, "pointer"); - void *ptr_one = mxGetData(ptr_field); - void **ptr = &ptr_one; + void **ptr = (void **) mxGetData(ptr_field); *ptr = (void*) pyobj; mxSetProperty(boxed, 0, "pointer", ptr_field); return boxed; @@ -146,8 +145,7 @@ PyObject *unbox (const mxArray *mxobj) { return PyErr_Format(MATLABError, "Unboxed pointer is null."); } else { - void *ptr_one = mxGetData(mxGetProperty(mxobj, 0, "pointer")); - void **ptr = &ptr_one; + void **ptr = (void **) mxGetData(mxGetProperty(mxobj, 0, "pointer")); return (PyObject *) *ptr; } } @@ -170,8 +168,7 @@ PyObject *unboxn (const mxArray *mxobj) { it does not check this before doing the mxGetProperty */ bool mxIsPyNull (const mxArray *mxobj) { - void *ptr_one = mxGetData(mxGetProperty(mxobj, 0, "pointer")); - void **ptr = &ptr_one; + void **ptr= (void **) mxGetData(mxGetProperty(mxobj, 0, "pointer")); return !*ptr; } From dbcc18fa4c507736c0057c00ae2f5bad13d19ffd Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Sat, 3 Jul 2010 12:03:59 +0100 Subject: [PATCH 18/21] update compiling_windows info --- COMPILING_WINDOWS.md | 58 +++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/COMPILING_WINDOWS.md b/COMPILING_WINDOWS.md index 956b910..c37847b 100644 --- a/COMPILING_WINDOWS.md +++ b/COMPILING_WINDOWS.md @@ -1,43 +1,35 @@ -# Compiling for Windows # +# Compiling for Windows with Microsoft Tools # -This is how I managed to compile pymex in Windows. There's probably -a better way, but I try not to use Windows that much myself. Maybe -I'll try one of Microsoft's compilers later, but MATLAB's lcc doesn't -seem to like Python's headers. +This branch compiles on Windows using the free (as in beer) Microsoft Visual +Studio 2008 Express Edition. This seems the easiest compiler to use for building +64bit (it is hard to build mex64 files with mingw-64 on windows). You will need: -1. [cygwin](http://www.cygwin.com/) -2. [MinGW](http://www.mingw.org/) -3. Python 2.6 for Windows (not just the cygwin version) -4. [gnumex](http://gnumex.sourceforge.net/) +1. [Microsoft Visual Studio 2008 Express Edition](http://www.microsoft.com/express/downloads/) +2. [Microsoft Windows SDK](http://msdn.microsoft.com/en-us/windows/bb980924.aspx) +3. [Python 2.6 for Windows](http://python.org/download/) -Tell gnumex where both cygwin and MinGW are, but configure it for a MinGW build. -If you haven't already, check out pymex and make sure you're on the win32 branch -(the Makefile is different). If you don't have git already, consider using your -cygwin installer to get it, otherwise just make sure to get the right archive -from GitHub. +The SDK is only required for [64 bit](http://tinyurl.com/3afmcka) (it extends VS +Express Edition with 64 bit tools). I used *Microsoft Windows SDK for Windows 7 +and .NET Framework 3.5 Service Pack 1* (I think Framework 3.5 matches VS 2008 +version). With these installed you should be able to run `mex -setup`. -Now, in Cygwin's bash, travel to the pymex directory and run `make`. If your Python26 -directory is somewhere other than C:\Python26, you'll need to tell make about it: -`make PYDIR=D:/MyStuff/Python26`. Use normal slashes, not backslashes. - -# Notes # - -Why mingw *and* cygwin? -Cygwin has useful tools like `make` and `git`, but for some reason gnumex does not -produce an appropriate set of mex options for cygwin's gcc (at least for me). -Compiling with MinGW and the standard Python for Windows also avoids depdendence on -Cygwin. The compiled mexw32 or mexw64 file should only require Python to work. -Of course, if you have installed the right msys ports you can probably do without cygwin. +With mex setup correctly there is a `makeall.m` file which runs a one line mex +command to build the package. You may need to adjust the paths there to point to +your Python installation. # Binaries # -If MATLAB's `mexext` command tells you `mexw32`, then you may be able to skip the compilation -and just drop [pymex.mexw32](http://cloud.github.com/downloads/kw/pymex/pymex.mexw32) into your -pymex directory. You do still need the pymex distribution and to have Python 2.6 installed. There -is currently no difference between this and the master branch other than compilation, so it shouldn't -matter which branch you have out. Note that this binary was compiled under MATLAB 2008b in Windows 7 -with MinGW's gcc. I have no idea whether it will work on other configurations. +If MATLAB's `mexext` command tells you `mexw64`, then you may be able to skip +the compilation and just drop +[pymex.mexw64](http://cloud.github.com/downloads/robince/pymex/pymex.mexw64) +into your pymex directory. You do still need the pymex distribution and to have +Python 2.6 installed. There is currently no difference between this and the +master branch other than small changes to enable compilation with Visual Studio, +so it shouldn't matter which branch you have out. Note that this binary was +compiled under MATLAB 2009a in Windows 7 with VS 2008 EE. It should work with +newer versions of MATLAB (but not older), not sure about other windows versions. +You may need the [VS 2008 Redistributable Package](http://tinyurl.com/6rm54q) + -There is presently no `mexw64` binary available. Sorry. \ No newline at end of file From c7f236c92894279d59fb0e03ceb9a57223a2eb1b Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Mon, 25 Jul 2011 16:00:11 +0200 Subject: [PATCH 19/21] clean up macro changes --- commands.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/commands.c b/commands.c index fae7127..acb7f1a 100755 --- a/commands.c +++ b/commands.c @@ -207,7 +207,6 @@ PYMEX(CALL, 2,3, if (kwargs && !PyDict_Check(kwargs)) mexErrMsgIdAndTxt("python:NoKWargs", "kwargs must be a dict or null"); } - #if PYMEX_DEBUG_FLAG PyObject *crepr = PyObject_Repr(callobj); PyObject *arepr = PyObject_Repr(args); PyObject *krepr = kwargs ? PyObject_Repr(kwargs) : NULL; @@ -220,7 +219,6 @@ PYMEX(CALL, 2,3, Py_XDECREF(crepr); Py_XDECREF(arepr); Py_XDECREF(krepr); - #endif PyObject *result = PyObject_Call(callobj, args, kwargs); plhs[0] = box(result); }) From 61a5f4f72b0e80436e927abf6c3a9fc5f1b763f0 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Mon, 25 Jul 2011 16:03:30 +0200 Subject: [PATCH 20/21] Fix memory leak in CALL (reference to args tuple not released) --- commands.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/commands.c b/commands.c index acb7f1a..f166d10 100755 --- a/commands.c +++ b/commands.c @@ -198,7 +198,7 @@ PYMEX(CALL, 2,3, if (mxIsCell(prhs[1])) args = mxCell_to_PyTuple(prhs[1]); else - args = unbox(prhs[1]); + args = unboxn(prhs[1]); if (!args || !PyTuple_Check(args)) mexErrMsgIdAndTxt("python:NotTuple", "args must be a tuple"); PyObject *kwargs = NULL; @@ -221,6 +221,7 @@ PYMEX(CALL, 2,3, Py_XDECREF(krepr); PyObject *result = PyObject_Call(callobj, args, kwargs); plhs[0] = box(result); + Py_XDECREF(args); }) #else PYMEX(CALL, 2,3, @@ -236,7 +237,7 @@ PYMEX(CALL, 2,3, if (mxIsCell(prhs[1])) args = mxCell_to_PyTuple(prhs[1]); else - args = unbox(prhs[1]); + args = unboxn(prhs[1]); if (!args || !PyTuple_Check(args)) mexErrMsgIdAndTxt("python:NotTuple", "args must be a tuple"); PyObject *kwargs = NULL; @@ -247,6 +248,7 @@ PYMEX(CALL, 2,3, } PyObject *result = PyObject_Call(callobj, args, kwargs); plhs[0] = box(result); + Py_XDECREF(args); }) #endif From 98b066bbaef72259102b9ac6dab3999514475593 Mon Sep 17 00:00:00 2001 From: Robin Ince Date: Sat, 9 Nov 2013 11:50:47 +0000 Subject: [PATCH 21/21] unpy arrays with trailing singleton dimensions --- pymexutil.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pymexutil.py b/pymexutil.py index ec7c82f..bf1be71 100644 --- a/pymexutil.py +++ b/pymexutil.py @@ -135,6 +135,12 @@ def numpy_ndarray_unpy(self): See Issue #5 ''' self = np.atleast_2d(self) + # handle trailing singleton dimensions + if self.ndim > 2 and self.shape[-1] == 1: + # need to squeeze + # should really squeeze only last axis but + # axis kw only supported in >1.7.0 + self = np.squeeze(self) mxclass = select_mxclass_by_dtype(self.dtype.type) cobj = mx.create_numeric_array(mxclass = mxclass, dims = self.shape)