Implementing a "classmethod" in an extension type

Thomas Heller theller at python.net
Tue Apr 1 10:09:55 EST 2003


"Mark Franklin" <mfranklin at tcsi.com> writes:

> Hi,
> 
> I've got an built-in extension type, implemented in C. I want to be able to implement the equivalent of a "classmethod" in that type. 
> 
> I thought I might be able to do something like this, which fairly closely mimics what you do in Python:
> 
> 	PyTypeObject myType = {
> 		// initialised in the usual way. It's tp_methods field includes a method definition for "MyMethod".......
> 	};
> 
> 	PyObject *method = PyObject_GetAttrString(myType, "MyMethod");
> 	// method is a PyMethodDescrObject
> 	PyObject *classMethod = PyClassMethod_New(method);
> 	PyObject_SetAttrString(myType, "MyMethod", classMethod);
> 	Py_DECREF(method);
> 
> 	PyType_Ready(myType);
> 
> 
> However, when I do this I get a TypeError exception from the PyObject_SetAttrString call: "can't set attributes of built-in/extension type 'MyType' ".
> 
> So, how do I get the class method into the type object?
> 
> 
> Thanks,
> Mark

In Python 2.3, there is a METH_CLASS flag. Unfortunately not in 2.2.
Here are the relevant snippets that I use - it is from
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/ctypes/ctypes/source/_ctypes.c
and it compiles with Python 2.2 as well as 2.3.

HTH,

Thomas


#include "Python.h"

#ifndef METH_CLASS
#define METH_CLASS 0x0010 /* from Python 2.3 */
#define NO_METH_CLASS
#endif

...

/*
 * If this is a real C classmethod (Python 2.3 and later),
 * it has METH_O style. So the type is in the first argument,
 * and the arg in the second.
 *
 * We fake this in Python 2.2, where METH_CLASS is not present,
 * and 'args' is a tuple containing the type as first member.
 */
static PyObject *
CString_from_param(PyObject *cls, PyObject *args)
{
	PyObject *value;

#ifdef NO_METH_CLASS
	PyObject *ignore;

	if (!PyArg_ParseTuple(args, "OO", &ignore, &value))
		return NULL;
#else
	value = args;
#endif
...
}


static PyMethodDef CString_methods[] = {
#ifdef NO_METH_CLASS /* Python 2.2 */
	{ "from_param", CString_from_param, METH_VARARGS | METH_CLASS,
#else
	{ "from_param", CString_from_param, METH_O | METH_CLASS,
#endif
	  from_param_doc },
	{ NULL, NULL },
};


...

	if (PyType_Ready(&CString_Type) < 0)
		return;
#ifdef NO_METH_CLASS
	DoClassMethods(&CString_Type);
#endif
	PyModule_AddObject(m, "c_string", (PyObject *)&CString_Type);





More information about the Python-list mailing list