How to pickle a C struct?
Dave Cole
djc at object-craft.com.au
Tue Feb 13 20:05:28 EST 2001
>>>>> "Michael" == Michael Husmann <Michael.Husmann at teleatlas.com> writes:
Michael> I have SWIG(ed) a C library with lots of structs and wanted
Michael> to use the shelve module to store some data on harddisk.
Michael> Those data contains a simple C struct. I have read that I
Michael> have to add the two functions __getstate__() and
Michael> __setstate__() in addmethods for storing and retrieving.
Michael> Is there someone who has done so to give me an example.
I thought you had to do that too. You need to use the copy_reg
module. Here is some code from my Sybase module which allows you to
pickle the numeric type I implemented.
There is probably more code here than you need, but I would prefer to
err on the side of caution.
- Dave
- - from numeric.c - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/* Implement the Sybase.numeric() method
*/
PyObject *NumericType_new(PyObject *module, PyObject *args)
{
NumericObj *self;
int precision, scale;
PyObject *obj;
self = PyObject_NEW(NumericObj, &NumericType);
if (self == NULL)
return NULL;
precision = -1;
scale = -1;
if (PyArg_ParseTuple(args, "O|ii", &obj, &precision, &scale)) {
NumericObj *num = NULL;
if (PyInt_Check(obj))
num = Numeric_FromInt(obj, precision, scale);
else if (PyLong_Check(obj))
num = Numeric_FromLong(obj, precision, scale);
else if (PyFloat_Check(obj))
num = Numeric_FromFloat(obj, precision, scale);
else if (PyString_Check(obj))
num = Numeric_FromString(obj, precision, scale);
else if (Numeric_Check(obj))
num = Numeric_FromNumeric(obj, precision, scale);
else
raise_exception_string(DataError, "could not convert to Numeric");
if (num)
return (PyObject*)num;
}
Py_DECREF(self);
return NULL;
}
/* Used in unpickler
*/
static PyObject *numeric_constructor = NULL;
/* Register the numeric type with the copy_reg module. This allows
* Python to (un)pickle numeric objects. The equivalent Python code
* is this:
*
* def pickle_numeric(n):
* return numeric, (str(n), n.precision, n.scale)
*
* copy_reg.pickle(type(numeric(1)), pickle_numeric, numeric)
*/
/* Numeric pickling function
*/
PyObject *pickle_numeric(PyObject *module, PyObject *args)
{
NumericObj *obj = NULL;
PyObject *values = NULL,
*tuple = NULL;
char text[NUMERIC_LEN];
if (!PyArg_ParseTuple(args, "O!", &NumericType, &obj))
goto error;
numeric_as_string(obj, text);
if ((values = Py_BuildValue("(sii)", text,
obj->num.precision, obj->num.scale)) == NULL)
goto error;
tuple = Py_BuildValue("(OO)", numeric_constructor, values);
error:
Py_XDECREF(values);
return tuple;
}
/* Register Numeric type pickler
*/
void copy_reg_numeric(PyObject *dict)
{
PyObject *module = NULL,
*pickle_func = NULL,
*pickler = NULL,
*obj = NULL;
module = PyImport_ImportModule("copy_reg");
if (module == NULL)
goto error;
if ((pickle_func = PyObject_GetAttrString(module, "pickle")) == NULL)
goto error;
if ((numeric_constructor = PyDict_GetItemString(dict, "numeric")) == NULL)
goto error;
if ((pickler = PyDict_GetItemString(dict, "pickle_numeric")) == NULL)
goto error;
Py_XINCREF(numeric_constructor);
obj = PyObject_CallFunction(pickle_func, "OOO",
&NumericType, pickler, numeric_constructor);
error:
Py_XDECREF(obj);
Py_XDECREF(pickler);
Py_XDECREF(pickle_func);
Py_XDECREF(module);
}
- - from Sybase.c - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static struct PyMethodDef Sybase_methods[] = {
{ "connect", (PyCFunction)ConnectType_new, METH_VARARGS | METH_KEYWORDS },
{ "numeric", (PyCFunction)NumericType_new, METH_VARARGS },
{ "pickle_numeric", (PyCFunction)pickle_numeric, METH_VARARGS },
{ NULL, NULL }
};
void initSybase(void)
{
PyObject *module;
PyObject *dict;
module = Py_InitModule(module_name, Sybase_methods);
dict = PyModule_GetDict(module);
:
:
copy_reg_numeric(dict);
}
--
http://www.object-craft.com.au
More information about the Python-list
mailing list