implementing reduce protocol in C

Tom Widrick lordmacro at hotmail.com
Fri Sep 20 06:14:53 EDT 2002


Alex Martelli wrote:
> This is stealing references to the five objects you pass as items.
> I'm not sure what effects this might have, but doesn't look good.
> Perhaps it's a contributing factor to strange behavior (though it
> would cause anomalies at pickling time, not when unpickling...).
> 
> Looks like a leak (no decref of args) but that's not the specific
> problem's that's biting you, I think.
> 

Plain as the blank stare on my face, I'm a CPython newbie :)

static PyObject *
proto_reduce(self)
	HyProtoObject *self;
{
	PyObject *args;
	PyObject *result;

	args = PyTuple_New(5);
	if(args == NULL)
		return NULL;

	PyTuple_SET_ITEM(args, 0, self->po_name);
	Py_INCREF(self->po_name);
	PyTuple_SET_ITEM(args, 1, self->po_parents);
	Py_INCREF(self->po_parents);
	PyTuple_SET_ITEM(args, 2, self->po_children);
	Py_INCREF(self->po_children);
	PyTuple_SET_ITEM(args, 3, self->po_doc);
	Py_INCREF(self->po_doc);
	PyTuple_SET_ITEM(args, 4, self->po_dict);
	Py_INCREF(self->po_dict);

	result = Py_BuildValue("(OOO)", self->ob_type, Py_None, args);
	Py_DECREF(args);
	return result;
};

Any better?

> Do you expose this as the __basicnew__ static method of your type?
> I'm not sure how you do so, as the definition of staticmethod
> lives in funcobject.c, not exposed in the .h, I think.  Or, ditto
> for classmethod.  Haven't tried exposing a __basicnew__ method
> from a C-coded type, yet.  If I had to, I think I'd try to run
> from C the Python-level exposed staticmethod built-in -- but since
> as I said I didn't try that yet, I may be missing something.
> Alex

I have stuck it into my methodlist as follows:

static PyMethodDef proto_methodlist[] = {
	{"chparents",	 (PyCFunction)proto_chparents, METH_VARARGS,
	  "change the parents of the object"},
	{"__basicnew__", (PyCFunction)proto_basicnew, METH_NOARGS,
	 "helper for pickle"},
	{"__reduce__",   (PyCFunction)proto_reduce, METH_NOARGS,
	 "helper for pickle"},
	{"__setstate__", (PyCFunction)proto_setstate, METH_VARARGS,
	 "helper for pickle"},
	{0}
};

I see. I did not know that basicnew had to be a staticmethod on my type.
That may have something to do with the problem, and I do not know how
to make a staticmethod on a C type either. In the doc, it says no 
arguments at all, and I assume the only way to do that is to have it a 
staticmethod? I'll scour the source to see if I can find a way to do
that.

How was this done prior to staticmethods? Was there no support for the 
basicnew way of doing it?

Thanks,
Tom





More information about the Python-list mailing list