/* This module exports part of the C API to the XDR routines into Python. * XDR is Sun's eXternal Data Representation, as described in RFC 1014. This * module is used by xdrlib.py to support the float and double data types * which are too much of a pain to support in Python directly. It is * not required by xdrlib.py -- when not available, these types aren't * supported at the Python layer. Note that representations that can be * implemented solely in Python, are *not* reproduced here. * * Module version number: 1.0 * * See xdrlib.py for usage notes. * * Note: this has so far, only been tested on Solaris 2.5 and IRIX 5.3. On * these systems, you will need to link with -lnsl for these symbols to be * defined. */ #include "Python.h" #include #include #include static PyObject* xdr_error; static PyObject* pack_float(self, args) PyObject* self; PyObject* args; { XDR xdr; float value; union { /* guarantees proper alignment */ long dummy; char buffer[4]; } addr; PyObject* rtn = NULL; if (!PyArg_ParseTuple(args, "f", &value)) return NULL; xdr.x_ops = NULL; xdrmem_create(&xdr, addr.buffer, 4, XDR_ENCODE); if( xdr.x_ops == NULL ) PyErr_SetString(xdr_error, "XDR stream initialization failed."); else if (xdr_float(&xdr, &value)) rtn = PyString_FromStringAndSize(addr.buffer, 4); else PyErr_SetString(xdr_error, "conversion from float failed"); xdr_destroy(&xdr); return rtn; } static PyObject* pack_double(self, args) PyObject* self; PyObject* args; { XDR xdr; double value; union { /* guarantees proper alignment */ long dummy; char buffer[8]; } addr; PyObject* rtn = NULL; if (!PyArg_ParseTuple(args, "d", &value)) return NULL; xdr.x_ops = NULL; xdrmem_create(&xdr, addr.buffer, 8, XDR_ENCODE); if( xdr.x_ops == NULL ) PyErr_SetString(xdr_error, "XDR stream initialization failed."); else if (xdr_double(&xdr, &value)) rtn = PyString_FromStringAndSize(addr.buffer, 8); else PyErr_SetString(xdr_error, "conversion from double failed"); xdr_destroy(&xdr); return rtn; } static PyObject* unpack_float(self, args) PyObject* self; PyObject* args; { XDR xdr; float value; char* string; int strlen; PyObject* rtn = NULL; if (!PyArg_ParseTuple(args, "s#", &string, &strlen)) return NULL; if (strlen != 4) { PyErr_SetString(PyExc_ValueError, "4 byte string expected"); return NULL; } /* Python guarantees that the string is 4 byte aligned */ xdr.x_ops = NULL; xdrmem_create(&xdr, (caddr_t)string, 4, XDR_DECODE); if( xdr.x_ops == NULL ) PyErr_SetString(xdr_error, "XDR stream initialization failed."); else if (xdr_float(&xdr, &value)) rtn = Py_BuildValue("f", value); else PyErr_SetString(xdr_error, "conversion to float failed"); xdr_destroy(&xdr); return rtn; } static PyObject* unpack_double(self, args) PyObject* self; PyObject* args; { XDR xdr; double value; char* string; int strlen; PyObject* rtn; if (!PyArg_ParseTuple(args, "s#", &string, &strlen)) return NULL; if (strlen != 8) { PyErr_SetString(PyExc_ValueError, "8 byte string expected"); return NULL; } /* Python guarantees that the string is 4 byte aligned */ xdr.x_ops = NULL; xdrmem_create(&xdr, (caddr_t)string, 8, XDR_DECODE); if( xdr.x_ops == NULL ) PyErr_SetString(xdr_error, "XDR stream initialization failed."); else if (xdr_double(&xdr, &value)) rtn = Py_BuildValue("d", value); else PyErr_SetString(xdr_error, "conversion to double failed"); xdr_destroy(&xdr); return rtn; } static struct PyMethodDef xdr_methods[] = { {"pack_float", pack_float, 1}, {"pack_double", pack_double, 1}, {"unpack_float", unpack_float, 1}, {"unpack_double", unpack_double, 1}, {NULL, NULL, 0} /* sentinel */ }; void init_xdr() { PyObject* module; PyObject* dict; module = Py_InitModule("_xdr", xdr_methods); dict = PyModule_GetDict(module); xdr_error = PyString_FromString("_xdr.error"); PyDict_SetItemString(dict, "error", xdr_error); }