Defining *class* methods on C code
Thomas Heller
theller at python.net
Fri Feb 6 10:31:46 EST 2004
Michael Hudson <mwh at python.net> writes:
> Thomas Heller <theller at python.net> writes:
>
>> I once knew how to do it, but I cannot find or remember it anymore:
>>
>> How can I attach *class* methods to a type in C code, when I have a
>> function
>>
>> PyObject *func(PyObject *type, PyObject *arg);
>>
>> with the METH_O calling convention? The type is already created, I
>> cannot insert it into the tp_methods array anymore.
>>
>> Something like this:
>>
>> class X(object):
>> pass
>>
>> def func(cls, arg):
>> ....
>>
>> X.func = classmethod(func)
>
> Just stuff it into tp_dict? You'll need to make the method object
> yourself, but that's easy.
>
> I think you probably have to hope that the name of the class method
> isn't a special method name (you'd want to call
> typeobject.c:update_slots then, but I don't think you can arrange for
> that to happen from outside typeobject.c as all the juicy symbols are
> static).
No special names. Here's the code:
static PyObject *my_method(PyObject *self, PyObject *arg)
{
Py_INCREF(arg);
return arg;
}
static PyMethodDef my_methods[] = {
{ "my_method", my_method, METH_O },
{ NULL, NULL },
};
and then ('type' is the type where I want to create the class method on):
if (somecondition) {
PyObject *func;
PyObject *meth;
PyMethodDef *ml = my_methods;
for (; ml->ml_name; ++ml) {
func = PyCFunction_New(ml, NULL);
if (!func)
return NULL;
meth = PyClassMethod_New(func);
if (!meth)
return NULL;
if (-1 == PyDict_SetItemString(result->tp_dict,
ml->ml_name,
meth))
return NULL;
}
}
I know that there are refcount leaks in this snippet, but that's not the
point.
Trying out the method:
c:\sf\ctypes>py23 -c "from ctypes import *; print c_int.my_method()"
<class 'ctypes.c_int'>
c:\sf\ctypes>py23 -c "from ctypes import *; print c_int.my_method(0)"
Traceback (most recent call last):
File "<string>", line 1, in ?
TypeError: my_method() takes exactly one argument (2 given)
c:\sf\ctypes>
Works *nearly*, but I would have expected that the method accepts one
parameter, pass it as 'arg' to the C function, plus the type itself as
'self'.
> Or just stick TP_HEAPTYPE into tp_flags, use PyObject_SetAttr and take
> TP_HEAPTYPE out again (that's very sick, though).
Um, why that?
Thanks,
Thomas
More information about the Python-list
mailing list