diff options
Diffstat (limited to 'bindings')
| -rw-r--r-- | bindings/Makefile.am | 11 | ||||
| -rw-r--r-- | bindings/python/Makefile.am | 7 | ||||
| -rw-r--r-- | bindings/python/pyzmq.cpp | 528 | ||||
| -rw-r--r-- | bindings/python/setup.py.in | 14 | 
4 files changed, 560 insertions, 0 deletions
| diff --git a/bindings/Makefile.am b/bindings/Makefile.am new file mode 100644 index 0000000..2b877ed --- /dev/null +++ b/bindings/Makefile.am @@ -0,0 +1,11 @@ +if BUILD_JAVA +DIR_J = java +endif + +if BUILD_PYTHON +DIR_P = python +endif + +SUBDIRS = $(DIR_J) $(DIR_P) +DIST_SUBDIRS = java python + 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]) + + | 
