summaryrefslogtreecommitdiff
path: root/bindings/python
diff options
context:
space:
mode:
Diffstat (limited to 'bindings/python')
-rw-r--r--bindings/python/Makefile.am7
-rw-r--r--bindings/python/pyzmq.cpp528
-rw-r--r--bindings/python/setup.py.in14
3 files changed, 549 insertions, 0 deletions
diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am
new file mode 100644
index 0000000..effe8b9
--- /dev/null
+++ b/bindings/python/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/libzmq \
+-I$(top_builddir)/libzmq $(PYTHON_INCLUDES)
+
+pyexec_LTLIBRARIES = libpyzmq.la
+libpyzmq_la_SOURCES = pyzmq.cpp
+libpyzmq_la_LIBADD = $(top_builddir)/src/libzmq.la
+libpyzmq_la_LDFLAGS = -avoid-version
diff --git a/bindings/python/pyzmq.cpp b/bindings/python/pyzmq.cpp
new file mode 100644
index 0000000..628d037
--- /dev/null
+++ b/bindings/python/pyzmq.cpp
@@ -0,0 +1,528 @@
+/*
+ Copyright (c) 2007-2009 FastMQ Inc.
+
+ This file is part of 0MQ.
+
+ 0MQ is free software; you can redistribute it and/or modify it under
+ the terms of the Lesser GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ 0MQ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ Lesser GNU General Public License for more details.
+
+ You should have received a copy of the Lesser GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stddef.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <Python.h>
+
+#include "../c/zmq.h"
+
+#if defined _MSC_VER
+#pragma warning (push)
+#pragma warning (disable:4996)
+#endif
+
+struct context_t
+{
+ PyObject_HEAD
+ void *handle;
+};
+
+PyObject *context_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ context_t *self = (context_t*) type->tp_alloc (type, 0);
+
+ if (self)
+ self->handle = NULL;
+
+ return (PyObject*) self;
+}
+
+
+int context_init (context_t *self, PyObject *args, PyObject *kwdict)
+{
+ int app_threads;
+ int io_threads;
+ static const char *kwlist [] = {"app_threads", "io_threads", NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "ii", (char**) kwlist,
+ &app_threads, &io_threads)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return -1; // ?
+ }
+
+ assert (!self->handle);
+ self->handle = zmq_init (app_threads, io_threads);
+ if (!self->handle) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return -1; // ?
+ }
+
+ return 0;
+}
+
+void context_dealloc (context_t *self)
+{
+ if (self->handle) {
+ int rc = zmq_term (self->handle);
+ if (rc != 0)
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ }
+
+ self->ob_type->tp_free ((PyObject*) self);
+}
+
+struct socket_t
+{
+ PyObject_HEAD
+ void *handle;
+};
+
+PyObject *socket_new (PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ socket_t *self = (socket_t*) type->tp_alloc (type, 0);
+
+ if (self)
+ self->handle = NULL;
+
+ return (PyObject*) self;
+}
+
+int socket_init (socket_t *self, PyObject *args, PyObject *kwdict)
+{
+ context_t *context;
+ int socket_type;
+ static const char *kwlist [] = {"context", "type", NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "Oi", (char**) kwlist,
+ &context, &socket_type)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+ // TODO: Check whether 'context' is really a libpyzmq.Context object.
+
+ assert (!self->handle);
+ self->handle = zmq_socket (context->handle, socket_type);
+ if (!self->handle) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return -1; // ?
+ }
+
+ return 0;
+}
+
+void socket_dealloc (socket_t *self)
+{
+ if (self->handle) {
+ int rc = zmq_close (self->handle);
+ if (rc != 0)
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ }
+
+ self->ob_type->tp_free ((PyObject*) self);
+}
+
+PyObject *socket_setsockopt (socket_t *self, PyObject *args, PyObject *kwdict)
+{
+ int option;
+ PyObject* optval;
+ static const char *kwlist [] = {"option", "optval", NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "iO", (char**) kwlist,
+ &option, &optval)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+
+ int rc = 0;
+
+ switch (option) {
+ case ZMQ_HWM:
+ case ZMQ_LWM:
+ case ZMQ_SWAP:
+ case ZMQ_AFFINITY:
+ case ZMQ_RATE:
+ case ZMQ_RECOVERY_IVL:
+ case ZMQ_MCAST_LOOP:
+ {
+ int val = PyInt_AsLong (optval);
+ rc = zmq_setsockopt (self->handle, option, &val, sizeof (int));
+ break;
+ }
+ case ZMQ_IDENTITY:
+ case ZMQ_SUBSCRIBE:
+ case ZMQ_UNSUBSCRIBE:
+
+ rc = zmq_setsockopt (self->handle, option, PyString_AsString (optval),
+ PyString_Size (optval));
+ break;
+
+ default:
+ rc = -1;
+ errno = EINVAL;
+ }
+
+ if (rc != 0) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return NULL;
+ }
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+PyObject *socket_bind (socket_t *self, PyObject *args, PyObject *kwdict)
+{
+ char const *addr;
+ static const char *kwlist [] = {"addr", NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "s", (char**) kwlist,
+ &addr)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+
+ int rc = zmq_bind (self->handle, addr);
+ if (rc != 0) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return NULL;
+ }
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+PyObject *socket_connect (socket_t *self, PyObject *args, PyObject *kwdict)
+{
+ char const *addr;
+ static const char *kwlist [] = {"addr", NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "s", (char**) kwlist,
+ &addr)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+
+ int rc = zmq_connect (self->handle, addr);
+ if (rc != 0) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return NULL;
+ }
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+PyObject *socket_send (socket_t *self, PyObject *args, PyObject *kwdict)
+{
+ PyObject *msg; /* = PyString_FromStringAndSize (NULL, 0); */
+ int flags = 0;
+ static const char *kwlist [] = {"msg", "flags", NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "S|i", (char**) kwlist,
+ &msg, &flags)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+
+ zmq_msg_t data;
+ int rc = zmq_msg_init_size (&data, PyString_Size (msg));
+ if (rc != 0) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return NULL;
+ }
+ memcpy (zmq_msg_data (&data), PyString_AsString (msg),
+ zmq_msg_size (&data));
+
+ rc = zmq_send (self->handle, &data, flags);
+ int rc2 = zmq_msg_close (&data);
+ assert (rc2 == 0);
+
+ if (rc != 0 && errno == EAGAIN)
+ return PyBool_FromLong (0);
+
+ if (rc != 0) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return NULL;
+ }
+
+ return PyBool_FromLong (1);
+}
+
+PyObject *socket_flush (socket_t *self, PyObject *args, PyObject *kwdict)
+{
+ static const char *kwlist [] = {NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "", (char**) kwlist)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+
+ int rc = zmq_flush (self->handle);
+ if (rc != 0) {
+ PyErr_SetString (PyExc_SystemError, strerror (errno));
+ return NULL;
+ }
+
+ Py_INCREF (Py_None);
+ return Py_None;
+}
+
+PyObject *socket_recv (socket_t *self, PyObject *args, PyObject *kwdict)
+{
+ int flags = 0;
+ static const char *kwlist [] = {"flags", NULL};
+ if (!PyArg_ParseTupleAndKeywords (args, kwdict, "|i", (char**) kwlist,
+ &flags)) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+
+ zmq_msg_t msg;
+ int rc = zmq_msg_init (&msg);
+ assert (rc == 0);
+
+ rc = zmq_recv (self->handle, &msg, flags);
+
+ if (rc != 0 && errno == EAGAIN) {
+ Py_INCREF (Py_None);
+ return Py_None;
+ }
+
+ if (rc != 0) {
+ PyErr_SetString (PyExc_SystemError, "invalid arguments");
+ return NULL;
+ }
+
+ PyObject *result = PyString_FromStringAndSize ((char*) zmq_msg_data (&msg),
+ zmq_msg_size (&msg));
+ rc = zmq_msg_close (&msg);
+ assert (rc == 0);
+ return result;
+}
+
+static PyMethodDef context_methods [] =
+{
+ {
+ NULL
+ }
+};
+
+static PyTypeObject context_type =
+{
+ PyObject_HEAD_INIT (NULL)
+ 0,
+ "libpyzmq.Context", /* tp_name */
+ sizeof (context_t), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) context_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ "", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ context_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc) context_init, /* tp_init */
+ 0, /* tp_alloc */
+ context_new /* tp_new */
+};
+
+static PyMethodDef socket_methods [] =
+{
+ {
+ "setsockopt",
+ (PyCFunction) socket_setsockopt,
+ METH_VARARGS | METH_KEYWORDS,
+ "setsockopt (option, optval) -> None\n\n"
+ },
+ {
+ "bind",
+ (PyCFunction) socket_bind,
+ METH_VARARGS | METH_KEYWORDS,
+ "bind (addr) -> None\n\n"
+ },
+ {
+ "connect",
+ (PyCFunction) socket_connect,
+ METH_VARARGS | METH_KEYWORDS,
+ "connect (addr) -> None\n\n"
+ },
+ {
+ "send",
+ (PyCFunction) socket_send,
+ METH_VARARGS | METH_KEYWORDS,
+ "send (msg, [flags]) -> Bool\n\n"
+ },
+ {
+ "flush",
+ (PyCFunction) socket_flush,
+ METH_VARARGS | METH_KEYWORDS,
+ "flush () -> None\n\n"
+ },
+ {
+ "recv",
+ (PyCFunction) socket_recv,
+ METH_VARARGS | METH_KEYWORDS,
+ "recv ([flags]) -> String\n\n"
+ },
+ {
+ NULL
+ }
+};
+
+static PyTypeObject socket_type =
+{
+ PyObject_HEAD_INIT (NULL)
+ 0,
+ "libpyzmq.Socket", /* tp_name */
+ sizeof (socket_t), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor) socket_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ "", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ socket_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ (initproc) socket_init, /* tp_init */
+ 0, /* tp_alloc */
+ socket_new /* tp_new */
+};
+
+static PyMethodDef module_methods [] = {{ NULL, NULL, 0, NULL }};
+
+static const char* libpyzmq_doc =
+ "Python API for 0MQ lightweight messaging kernel.\n"
+ "For more information see http://www.zeromq.org.\n"
+ "0MQ is distributed under GNU Lesser General Public License v3.\n";
+
+#ifndef PyMODINIT_FUNC
+#define PyMODINIT_FUNC void
+#endif
+
+PyMODINIT_FUNC initlibpyzmq ()
+{
+ int rc = PyType_Ready (&context_type);
+ assert (rc == 0);
+ rc = PyType_Ready (&socket_type);
+ assert (rc == 0);
+
+ PyObject *module = Py_InitModule3 ("libpyzmq", module_methods,
+ libpyzmq_doc);
+ if (!module)
+ return;
+
+ Py_INCREF (&context_type);
+ PyModule_AddObject (module, "Context", (PyObject*) &context_type);
+ Py_INCREF (&socket_type);
+ PyModule_AddObject (module, "Socket", (PyObject*) &socket_type);
+
+ PyObject *dict = PyModule_GetDict (module);
+ assert (dict);
+ PyObject *t;
+ t = PyInt_FromLong (ZMQ_NOBLOCK);
+ PyDict_SetItemString (dict, "NOBLOCK", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_NOFLUSH);
+ PyDict_SetItemString (dict, "NOFLUSH", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_P2P);
+ PyDict_SetItemString (dict, "P2P", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_PUB);
+ PyDict_SetItemString (dict, "PUB", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_SUB);
+ PyDict_SetItemString (dict, "SUB", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_REQ);
+ PyDict_SetItemString (dict, "REQ", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_REP);
+ PyDict_SetItemString (dict, "REP", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_HWM);
+ PyDict_SetItemString (dict, "HWM", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_LWM);
+ PyDict_SetItemString (dict, "LWM", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_SWAP);
+ PyDict_SetItemString (dict, "SWAP", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_AFFINITY);
+ PyDict_SetItemString (dict, "AFFINITY", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_IDENTITY);
+ PyDict_SetItemString (dict, "IDENTITY", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_SUBSCRIBE);
+ PyDict_SetItemString (dict, "SUBSCRIBE", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_UNSUBSCRIBE);
+ PyDict_SetItemString (dict, "UNSUBSCRIBE", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_RATE);
+ PyDict_SetItemString (dict, "RATE", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_RECOVERY_IVL);
+ PyDict_SetItemString (dict, "RECOVERY_IVL", t);
+ Py_DECREF (t);
+ t = PyInt_FromLong (ZMQ_MCAST_LOOP);
+ PyDict_SetItemString (dict, "MCAST_LOOP", t);
+ Py_DECREF (t);
+
+}
+
+#if defined _MSC_VER
+#pragma warning (pop)
+#endif
diff --git a/bindings/python/setup.py.in b/bindings/python/setup.py.in
new file mode 100644
index 0000000..f7055d5
--- /dev/null
+++ b/bindings/python/setup.py.in
@@ -0,0 +1,14 @@
+from distutils.core import setup, Extension
+
+module1 = Extension('libpyzmq',
+ libraries = ['zmq'],
+ library_dirs = ['@prefix@/lib'],
+ include_dirs = ['@PYTHON_SETUP_INCLUDES@','@prefix@/include'],
+ sources = ['pyzmq.cpp'])
+
+setup (name = 'libyzmq',
+ version = '@VERSION@',
+ description = '0MQ Python library',
+ ext_modules = [module1])
+
+