Re: objc_addMethods
Re: objc_addMethods
- Subject: Re: objc_addMethods
- From: "b.bum" <email@hidden>
- Date: Thu, 11 Nov 2004 15:41:54 -0800
On Nov 11, 2004, at 2:32 PM, Tim Conkling wrote:
Does anybody have any sample code showing the proper use of
objc_addMethods to dynamically add methods to a class at runtime?
This is sort of me just being lazy, as I have the documentation in
front of me, but I can't figure out certain things like how to
correctly fill in an objc_method struct (what data goes into the
method_imp field, for example?).
Are there any hazards involved in adding methods to existing classes
at runtime (other than adding a method to a class that already has
that method defined?)
PyObjC provides API via which you can add Python functions as methods
on classes (or you can add existing Obj-C methods to other classes).
Not something I would recommend for anything but debugging purposes as
it introduces tremendous fragility, but quite handy in those times of
need.
>>> from objc import *
>>> from Foundation import *
>>> x = NSObject.new()
>>> x.description()
u'<NSObject: 0x37f1a0>'
>>> def description(self):
... print "Hello, World!"
...
>>> classAddMethods(NSObject, [description])
>>> x.description()
Hello, World!
Source here:
http://svn.red-bean.com/pyobjc/trunk/pyobjc/Modules/objc/module.m
Code Here:
PyDoc_STRVAR(classAddMethods_doc,
"classAddMethods(targetClass, methodsArray)\n"
"\n"
"Adds methods in methodsArray to class. The effect is similar to
how \n"
"categories work. If class already implements a method as defined
in \n"
"methodsArray, the original implementation will be replaced by the
\n"
"implementation from methodsArray.");
static PyObject*
classAddMethods(PyObject* self __attribute__((__unused__)),
PyObject* args, PyObject* keywds)
{
static char* kwlist[] = { "targetClass", "methodsArray", NULL };
PyObject* classObject = NULL;
PyObject* methodsArray = NULL;
Class targetClass;
int methodCount;
int methodIndex;
struct objc_method_list *methodsToAdd;
if (!PyArg_ParseTupleAndKeywords(args, keywds,
"OO:classAddMethods", kwlist,
&classObject, &methodsArray)) {
return NULL;
}
if (!PyObjCClass_Check(classObject)) {
PyErr_SetString(PyExc_TypeError, "base class is not an Objective-C
class");
return NULL;
}
methodsArray = PySequence_Fast(
methodsArray, "methodsArray must be a sequence");
if (methodsArray == NULL) return NULL;
targetClass = PyObjCClass_GetClass(classObject);
methodCount = PySequence_Fast_GET_SIZE(methodsArray);
if (methodCount == 0) {
Py_INCREF(Py_None);
return Py_None;
}
methodsToAdd = PyObjCRT_AllocMethodList(methodCount);
if (methodsToAdd == NULL) {
PyErr_NoMemory();
return NULL;
}
methodsToAdd->method_count = methodCount;
for (methodIndex = 0; methodIndex < methodCount; methodIndex++) {
PyObject* aMethod = PySequence_Fast_GET_ITEM(
methodsArray, methodIndex);
struct objc_method *objcMethod;
aMethod = PyObjCSelector_FromFunction(
NULL,
aMethod,
classObject,
NULL);
if (aMethod == NULL) {
PyErr_SetString(PyExc_TypeError ,
"All objects in methodArray must be of "
"type <objc.selector>, <function>, "
" <method> or <classmethod>");
goto cleanup_and_return_error;
}
/* install in methods to add */
objcMethod = &methodsToAdd->method_list[methodIndex];
objcMethod->method_name = PyObjCSelector_GetSelector(aMethod);
objcMethod->method_types = strdup(
PyObjCSelector_Signature(aMethod));
if (objcMethod->method_types == NULL) {
goto cleanup_and_return_error;
}
objcMethod->method_imp = PyObjCFFI_MakeIMPForPyObjCSelector(
(PyObjCSelector*)aMethod);
Py_DECREF(aMethod);
}
/* add the methods */
PyObjCRT_ClassAddMethodList(targetClass, methodsToAdd);
Py_INCREF(Py_None);
return Py_None;
cleanup_and_return_error:
if (methodsToAdd) free(methodsToAdd);
return NULL;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden