Skip to content
This repository was archived by the owner on Jun 27, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
af98d68
Woohoo, got it to compile in windows with gcc
Dec 5, 2009
047b9b3
Merge branch 'master' into win32
Dec 5, 2009
ba41b37
markdown formatting issue
Dec 5, 2009
a938e63
Adding notes about win32 binary download
Dec 5, 2009
b300566
rename .c to .cpp for visual studio
robince Jul 2, 2010
58c2bb1
vs compatible vararg macro
robince Jul 2, 2010
f29db43
move preprocessor if out of macro (not expanded by visual studio)
robince Jul 2, 2010
37f7a67
explicit enum cast required for vs
robince Jul 2, 2010
d4d1300
explicit conversion for void * to void **
robince Jul 2, 2010
8e681b4
dynamic arrays for visual studio (used c++ dynamic arrays as it seeme…
robince Jul 2, 2010
14e15f1
unexpanded preprocessor definitions - dont seem essential in this case
robince Jul 2, 2010
c2990b6
change import to include... not sure if this will require tighter #if…
robince Jul 2, 2010
394cf2e
dynamically allocate dims
robince Jul 2, 2010
fa721b7
renamce class variable (c++ keyword)
robince Jul 2, 2010
2d9b8c5
another array allocation (subs)
robince Jul 2, 2010
15a790f
basic matlab make file
robince Jul 2, 2010
6591d31
mistake here - deleted inargs too soon
robince Jul 2, 2010
e898839
messed up box/unbox with dereferencing when all that was needed was a…
robince Jul 2, 2010
dbcc18f
update compiling_windows info
robince Jul 3, 2010
c7f236c
clean up macro changes
robince Jul 25, 2011
61a5f4f
Fix memory leak in CALL (reference to args tuple not released)
robince Jul 25, 2011
98b066b
unpy arrays with trailing singleton dimensions
robince Nov 9, 2013
1c96839
Merge branch 'win64' of github.com:robince/pymex into win64
robince Nov 9, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions COMPILING_WINDOWS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Compiling for Windows with Microsoft Tools #

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. [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/)

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`.

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 `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)


19 changes: 7 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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),)
Expand All @@ -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."
Expand Down
34 changes: 31 additions & 3 deletions commands.c
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand All @@ -197,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;
Expand All @@ -206,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;
Expand All @@ -219,10 +219,38 @@ 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);
Py_XDECREF(args);
})
#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 = unboxn(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);
Py_XDECREF(args);
})
#endif

PYMEX(IS_CALLABLE, 1,1,
"Tests the object to see if it is callable.",
Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions makeall.m
Original file line number Diff line number Diff line change
@@ -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
File renamed without changes.
25 changes: 15 additions & 10 deletions mexmodule.c → mexmodule.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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<nargin; i++) {
inargs[i] = Any_PyObject_to_mxArray(PyTuple_GetItem(args, i));
}
int tupleout = nargout >= 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)
delete [] inargs;
if (err) {
delete [] outargs;
return _raiselasterror(NULL);
}
else {
if (tupleout) {
PyObject *outseq = PyTuple_New(nargout);
Expand All @@ -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);
}
}
}

Expand All @@ -133,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;

Expand Down
28 changes: 18 additions & 10 deletions mxmodule.c → mxmodule.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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); \
Expand Down Expand Up @@ -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
Expand All @@ -59,17 +61,18 @@ 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));
else
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -225,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) {
Expand All @@ -238,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<len; i++) {
PyObject *ind = PyNumber_Index(PyTuple_GetItem(args, (Py_ssize_t) i));
if (PyErr_Occurred()) return NULL;
subs[i] = (mwIndex) PyLong_AsLong(ind);
}
return PyLong_FromLong(mxCalcSingleSubscript(mxobj, len, subs));
PyObject *returnobj = PyLong_FromLong(mxCalcSingleSubscript(mxobj, len, subs));
delete [] subs;
return returnobj;
}

static PyObject *mxArray_mxGetField(PyObject *self, PyObject *args, PyObject *kw) {
Expand Down
2 changes: 1 addition & 1 deletion pymex.c → pymex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pymex.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions pymexutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions sharedfuncs.c → sharedfuncs.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ 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 = (void **) mxGetData(ptr_field);
*ptr = (void*) pyobj;
mxSetProperty(boxed, 0, "pointer", ptr_field);
return boxed;
Expand All @@ -145,7 +145,7 @@ PyObject *unbox (const mxArray *mxobj) {
return PyErr_Format(MATLABError, "Unboxed pointer is null.");
}
else {
void **ptr = mxGetData(mxGetProperty(mxobj, 0, "pointer"));
void **ptr = (void **) mxGetData(mxGetProperty(mxobj, 0, "pointer"));
return (PyObject *) *ptr;
}
}
Expand All @@ -168,7 +168,7 @@ 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= (void **) mxGetData(mxGetProperty(mxobj, 0, "pointer"));
return !*ptr;
}

Expand Down