diff --git a/README.md b/README.md index 47dee20..2e1a852 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ extension, which provides a simple interface for weaving python and Matlab code together (requires ipython > 0.13). -***AT PRESENT THIS DOES NOT WORK ON WINDOWS*** - ## Installation Pymatbridge communicates with Matlab using zeromq. So before installing @@ -25,11 +23,11 @@ build and install zmq. After zmq is installed, make sure you can find the locati libzmq is installed. The library extension name and default location on different systems are listed below. -| Platform | library name | Default locations | -| ------------- | ------------- | -------------------------- | -| MacOS | libzmq.dylib | /usr/lib or /usr/local/lib | -| Linux | libzmq.so.3 | /usr/lib or /usr/local/lib | -| Windows | libzmq.dll | TBD | +| Platform | library name | Default locations | +| ------------- | ------------- | --------------------------------- | +| MacOS | libzmq.dylib | /usr/lib or /usr/local/lib | +| Linux | libzmq.so.3 | /usr/lib or /usr/local/lib | +| Windows | libzmq.dll | C:\Program Files\ZeroMQ 3.2.4\bin | If you specified a prefix when installing zmq, the library file should be located at the same prefix location. @@ -43,9 +41,9 @@ On Linux, add the following line to your .bash_profile: export LD_LIBRARY_PATH=$DYLD_LIBRARY_PATH: -On Windows, - - TBD +On Windows, add the install location of libzmq.dll to the PATH environment variable. +On Windows 7+, typing "environment variables" into the start menu will bring up the +apporpriate Control Panel links. ### Install pyzmq After step 1 is finished, please grab the latest version of @@ -131,9 +129,7 @@ sessions by adding code to the `~/startup.m` file. The Matlab magic allows you to use pymatbridge in the context of the IPython notebook format. - import pymatbridge as pymat - ip = get_ipython() - pymat.load_ipython_extension(ip) + %load_ext pymatbridge These lines will automatically start the matlab session for you. Then, you can simply decorate a line/cell with the '%matlab' or '%%matlab' decorator and diff --git a/messenger/mexw64/messenger.mexw64 b/messenger/mexw64/messenger.mexw64 new file mode 100644 index 0000000..9952c40 Binary files /dev/null and b/messenger/mexw64/messenger.mexw64 differ diff --git a/messenger/src/messenger.c b/messenger/src/messenger.c index b9cca29..beb9a03 100644 --- a/messenger/src/messenger.c +++ b/messenger/src/messenger.c @@ -6,15 +6,15 @@ /* Set a 200MB receiver buffer size */ #define BUFLEN 200000000 -void *ctx, *socket; +void *ctx, *socket_ptr; static int initialized = 0; /* Initialize a ZMQ server */ int initialize(char *socket_addr) { - + int rc; ctx = zmq_ctx_new(); - socket = zmq_socket(ctx, ZMQ_REP); - int rc = zmq_bind(socket, socket_addr); + socket_ptr = zmq_socket(ctx, ZMQ_REP); + rc = zmq_bind(socket_ptr, socket_addr); if (!rc) { initialized = 1; @@ -33,7 +33,7 @@ int listen(char *buffer, int buflen) { mexErrMsgTxt("Error: ZMQ session not initialized"); } - return zmq_recv(socket, buffer, buflen, 0); + return zmq_recv(socket_ptr, buffer, buflen, 0); } /* Sending out a message */ @@ -42,17 +42,16 @@ int respond(char *msg_out, int len) { mexErrMsgTxt("Error: ZMQ session not initialized"); } - int bytesent = zmq_send(socket, msg_out, len, 0); + return zmq_send(socket_ptr, msg_out, len, 0); - return bytesent; } /* Cleaning up after session finished */ void cleanup (void) { /* Send a confirmation message to the client */ - zmq_send(socket, "exit", 4, 0); + zmq_send(socket_ptr, "exit", 4, 0); - zmq_close(socket); + zmq_close(socket_ptr); mexPrintf("Socket closed\n"); zmq_term(ctx); mexPrintf("Context terminated\n"); @@ -62,14 +61,13 @@ void cleanup (void) { /* Gateway function with Matlab */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { - + char *cmd; /* If no input argument, print out the usage */ if (nrhs == 0) { mexErrMsgTxt("Usage: messenger('init|listen|respond', extra1, extra2, ...)"); } /* Get the input command */ - char *cmd; if(!(cmd = mxArrayToString(prhs[0]))) { mexErrMsgTxt("Cannot read the command"); } @@ -123,6 +121,8 @@ void mexFunction(int nlhs, mxArray *plhs[], /* Send a message out */ } else if (strcmp(cmd, "respond") == 0) { + size_t msglen; + char *msg_out; mxLogical *p; /* Check if the input format is valid */ @@ -130,8 +130,8 @@ void mexFunction(int nlhs, mxArray *plhs[], mexErrMsgTxt("Please provide the message to send"); } - size_t msglen = mxGetNumberOfElements(prhs[1]); - char *msg_out = mxArrayToString(prhs[1]); + msglen = mxGetNumberOfElements(prhs[1]); + msg_out = mxArrayToString(prhs[1]); plhs[0] = mxCreateLogicalMatrix(1, 1); p = mxGetLogicals(plhs[0]); diff --git a/pymatbridge/pymatbridge.py b/pymatbridge/pymatbridge.py index 5a135db..909df21 100644 --- a/pymatbridge/pymatbridge.py +++ b/pymatbridge/pymatbridge.py @@ -57,7 +57,7 @@ class Matlab(object): A class for communicating with a matlab session """ - def __init__(self, matlab='matlab', socket_addr='ipc:///tmp/pymatbridge', + def __init__(self, matlab='matlab', socket_addr=None, id='python-matlab-bridge', log=False, maxtime=60, platform=None, startup_options=None): """ @@ -104,9 +104,12 @@ def __init__(self, matlab='matlab', socket_addr='ipc:///tmp/pymatbridge', else: self.platform = platform + if self.socket_addr is None: # use the default + self.socket_addr = "tcp://127.0.0.1:55555" if self.platform == "win32" else "ipc:///tmp/pymatbridge" + if startup_options: self.startup_options = startup_options - elif self.platform == 'Windows': + elif self.platform == 'win32': self.startup_options = ' -automation -noFigureWindows' else: self.startup_options = ' -nodesktop -nodisplay' diff --git a/setup.py b/setup.py index bc27f56..d435232 100755 --- a/setup.py +++ b/setup.py @@ -13,27 +13,31 @@ from distutils.core import setup # Find the messenger binary file and copy it to /matlab folder. -bin_location = "" + +def copy_bin(bin_path): + if os.path.exists(bin_path): + shutil.copy(bin_path, "./pymatbridge/matlab") + return True + else: + return False + if sys.platform == "darwin": - if not os.path.exists("./messenger/mexmaci64/messenger.mexmaci64"): + if not copy_bin("./messenger/mexmaci64/messenger.mexmaci64"): raise ValueError("messenger.mexmaci64 is not built yet. Please build it yourself.") - bin_location = "./messenger/mexmaci64/messenger.mexmaci64" elif sys.platform == "linux2": - if not os.path.exists("./messenger/mexa64/messenger.mexa64"): + if not copy_bin("./messenger/mexa64/messenger.mexa64"): raise ValueError("messenger.mexa64 is not built yet. Please build it yourself.") - bin_location = "./messenger/mexa64/messenger.mexa64" elif sys.platform == "win32": - if not os.path.exists("./messenger/mexw32/messenger.mexw32"): - raise ValueError("messenger.mexw32 is not built yet. Please build it yourself.") - bin_location = "./messenger/mexw32/messenger.mexw32" + t1 = copy_bin("./messenger/mexw64/messenger.mexw64") + t2 = copy_bin("./messenger/mexw32/messenger.mexw32") + if not (t1 or t2): + raise ValueError("Neither messenger.mexw32 or mex264 is built yet. Please build the appropriate one yourself") else: raise ValueError("Known platform") -shutil.copy(bin_location, "./pymatbridge/matlab") - # Get version and release info, which is all stored in pymatbridge/version.py ver_file = os.path.join('pymatbridge', 'version.py') execfile(ver_file)