home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1996 by Lele Gaifax. All Rights Reserved
- *
- * This software may be used and distributed freely for any purpose
- * provided that this notice is included unchanged on any and all
- * copies. The author does not warrant or guarantee this software in
- * any way.
- *
- * This file is part of the PyObjC package.
- *
- * $RCSfile: ObjCMethod.m,v $
- * $Revision: 1.1.1.1 $
- * $Date: 1996/11/14 01:50:23 $
- *
- * Created Mon Oct 28 12:33:43 1996.
- */
-
- #include "ObjC.h"
- #include "objc_support.h"
-
- ObjCMethod *
- ObjCMethod_new_with_selector (ObjCObject *obj, SEL sel)
- {
- ObjCMethod *self = PyObject_NEW (ObjCMethod, &ObjCMethod_Type);
-
- if (!self)
- return NULL;
-
- self->obj = obj;
- Py_INCREF (self->obj);
- self->sel = sel;
-
- return self;
- }
-
- ObjCMethod *
- ObjCMethod_new_with_name (ObjCObject *obj, const char *meth_name)
- {
- SEL sel = SELUID(meth_name);
-
- if (!sel)
- {
- char error_msg[100];
-
- sprintf (error_msg, "Unknown method name: `%s'", meth_name);
- PyErr_SetString (ObjC_Error, error_msg);
- return NULL;
- }
- else
- return ObjCMethod_new_with_selector (obj, sel);
- }
-
- static void
- ObjCMethod_dealloc (ObjCMethod *self)
- {
- Py_DECREF (self->obj);
- PyMem_DEL (self);
- }
-
- static PyObject *
- ObjCMethod_repr (ObjCMethod *self)
- {
- char buffer[512];
-
- sprintf (buffer, "<Objective-C %s method `%s' on %s at %lx>",
- ISCLASS(self->obj->oc_object) ? "factory" : "instance",
- SELNAME(self->sel),
- NAMEOF(self->obj->oc_object), (long) self);
- return PyString_FromString (buffer);
- }
-
- static char ObjCMethod_pack_argument_doc[] =
- FUNDOC("Pack one of the method's arguments into an object suitable to be used in a\n\
- succeding call of the method, possibly initialized with a value. This is valid\n\
- only for pointer-argument, aka pass-by-reference.",
- ".pack_argument (N, VALUE)",
- "N\t: apply to the Nth argument of this method\n\
- \t\tVALUE\t: optional initializer value",
- "An ObjCPointer instance");
- static PyObject *
- ObjCMethod_pack_argument (ObjCMethod *meth, PyObject *args)
- {
- unsigned int argn;
- PyObject *value = NULL;
-
- if (PyArg_ParseTuple (args, "i|O;argument number and a facultative initializator object", &argn, &value))
- {
- METHOD methinfo;
- unsigned int argcount;
-
- if (ISCLASS(meth->obj->oc_object))
- methinfo = CLASSMETH(meth->obj->oc_object, meth->sel);
- else
- methinfo = INSTMETH(meth->obj->oc_object, meth->sel);
-
- if (!methinfo)
- {
- #define ERRORMSG " does not recognize `"
- const char *whoiam = NAMEOF(meth->obj->oc_object);
- const char *selname = SELNAME(meth->sel);
- char buffer[strlen (whoiam) + sizeof ERRORMSG + 1 + strlen (selname) + 1 + 1];
-
- strcpy (buffer, whoiam);
- strcat (buffer, ERRORMSG);
- strcat (buffer, (ISCLASS(meth->obj->oc_object) ? "+" : "-"));
- strcat (buffer, selname);
- strcat (buffer, "'");
- PyErr_SetString (ObjC_Error, buffer);
- #undef ERRORMSG
- return NULL;
- }
-
- argcount = METHNARGS(methinfo);
-
- if (argn < argcount-2)
- {
- const char *type;
- unsigned int size;
- char *buffer;
-
- #ifdef GNU_RUNTIME
- type = objc_skip_argspec (methinfo->method_types);
- type = objc_skip_argspec (type); // skip SELF
- type = objc_skip_argspec (type); // skip SEL
- while (argn--)
- type = objc_skip_argspec (type);
- #else
- unsigned int offset;
-
- method_getArgumentInfo (methinfo, argn+2, &type, &offset);
- #endif
-
- if (*type != _C_PTR)
- {
- PyErr_SetString (ObjC_Error, ".pack_argument() can be used on pointer-argument only");
- return NULL;
- }
-
- size = objc_sizeof_type (type+1);
-
- buffer = alloca (size);
- if (value)
- {
- const char *error = depythonify_c_value (type+1, value, &buffer);
-
- if (error)
- {
- const char *typeend = objc_skip_typespec (type+1);
- #define ERRMSG "expected %s for argument %d: its type is `%.*s'"
- char errmsg[sizeof ERRMSG + strlen (error) + typeend-type];
-
- sprintf (errmsg, ERRMSG, error, argn, (int) (typeend-type-1), type+1);
- PyErr_SetString (ObjC_Error, errmsg);
- #undef ERRMSG
- return NULL;
- }
- }
- else
- memset (buffer, 0, size);
-
- return (PyObject *) ObjCPointer_new (buffer, type+1);
- }
- else
- {
- PyErr_SetString (ObjC_Error, "argument index out of range");
- return NULL;
- }
- }
- return NULL;
- }
-
- static char ObjCMethod_unpack_argument_doc[] =
- FUNDOC("Translate a pass-by-reference argument' content into the Python representation.",
- ".unpack_argument (N, VALUE)",
- "N\t: apply to the Nth argument of this method\n\
- \t\tVALUE\t: its packed value",
- "A Python object");
- static PyObject *
- ObjCMethod_unpack_argument (ObjCMethod *meth, PyObject *args)
- {
- unsigned int argn;
- PyObject *value;
-
- if (PyArg_ParseTuple (args, "iO;argument number and the value to unpack (a string or ObjCPointer instance)",
- &argn, &value))
- {
- METHOD methinfo;
- unsigned int argcount;
-
- if (ISCLASS(meth->obj->oc_object))
- methinfo = CLASSMETH(meth->obj->oc_object, meth->sel);
- else
- methinfo = INSTMETH(meth->obj->oc_object, meth->sel);
-
- if (!methinfo)
- {
- #define ERRORMSG " does not recognize `"
- const char *whoiam = NAMEOF(meth->obj->oc_object);
- const char *selname = SELNAME(meth->sel);
- char buffer[strlen (whoiam) + sizeof ERRORMSG + 1 + strlen (selname) + 1 + 1];
-
- strcpy (buffer, whoiam);
- strcat (buffer, ERRORMSG);
- strcat (buffer, (ISCLASS(meth->obj->oc_object) ? "+" : "-"));
- strcat (buffer, selname);
- strcat (buffer, "'");
- PyErr_SetString (ObjC_Error, buffer);
- #undef ERRORMSG
- return NULL;
- }
-
- argcount = METHNARGS(methinfo);
-
- if (argn < argcount-2)
- {
- const char *type;
- char *buffer;
-
- #ifdef GNU_RUNTIME
- type = objc_skip_argspec (methinfo->method_types);
- type = objc_skip_argspec (type); // skip SELF
- type = objc_skip_argspec (type); // skil SEL
- while (argn--)
- type = objc_skip_argspec (type);
- #else
- unsigned int offset;
-
- method_getArgumentInfo (methinfo, argn+2, &type, &offset);
- #endif
-
- if (*type != _C_PTR)
- {
- PyErr_SetString (ObjC_Error, ".unpack_argument() can be used on pointer-argument only");
- return NULL;
- }
-
- type++;
- if (PyString_Check (value))
- {
- unsigned int expected_size = objc_sizeof_type (type);
-
- if (expected_size != PyString_Size (value))
- {
- #define ERRMSG "a string of size %d instead of %d"
- char errmsg[sizeof (ERRMSG)+6+6];
-
- sprintf (errmsg, ERRMSG, expected_size, PyString_Size (value));
- PyErr_SetString (ObjC_Error, errmsg);
- return NULL;
- #undef ERRMSG
- }
-
- buffer = PyString_AS_STRING ((PyStringObject *) value);
- }
- else if (ObjCPointer_Check (value))
- {
- const char *typeend = objc_skip_typespec (type);
- const char *vtype = PyString_AS_STRING (((ObjCPointer *) value)->type);
-
- if (strncmp (vtype, type, typeend - type))
- {
- #define ERRMSG "a pointer to `%.*s' instead of `%s'"
- char errmsg[sizeof (ERRMSG)+
- (typeend-type)+
- PyString_Size ((PyObject *) ((ObjCPointer *) value)->type)];
-
- sprintf (errmsg, ERRMSG, (int) (typeend-type), type, vtype);
-
- PyErr_SetString (ObjC_Error, errmsg);
- return NULL;
- #undef ERRMSG
- }
-
- buffer = ((ObjCPointer *) value)->ptr;
- }
- else
- {
- PyErr_BadArgument();
- return NULL;
- }
- return pythonify_c_value (type, buffer, meth);
- }
- else
- {
- PyErr_SetString (ObjC_Error, "argument index out of range");
- return NULL;
- }
- }
- return NULL;
- }
-
- static PyMethodDef ObjCMethod_methods[] =
- {
- { "pack_argument", (PyCFunction) ObjCMethod_pack_argument, METH_VARARGS, ObjCMethod_pack_argument_doc },
- { "unpack_argument", (PyCFunction) ObjCMethod_unpack_argument, METH_VARARGS, ObjCMethod_unpack_argument_doc },
- { 0, 0, 0, 0 }
- };
-
- static PyObject *
- ObjCMethod_getattr (ObjCMethod *self, char *name)
- {
- PyObject *method;
-
- method = Py_FindMethod (ObjCMethod_methods, (PyObject *) self, name);
- if (method)
- return method;
- else
- {
- PyErr_Clear();
-
- if (!strcmp (name, "name"))
- return PyString_FromString ((char *) SELNAME(self->sel));
- else if (!strcmp (name, "__members__"))
- {
- const char *members[] = { "name" };
- PyObject *list;
- unsigned int idx;
-
- idx = sizeof (members) / sizeof (members[0]);
- list = PyList_New (idx);
- while (idx--)
- PyList_SetItem (list, idx, PyString_FromString ((char *) members[idx]));
- return list;
- }
- }
-
- PyErr_SetString (PyExc_AttributeError, name);
- return NULL;
- }
-
- static PyObject *
- ObjCMethod_call (ObjCMethod *self, PyObject *args, PyObject *kw)
- {
- PyObject *retobject = execute_and_pythonify_objc_method (self, args);
-
- return retobject;
- }
-
- PyTypeObject ObjCMethod_Type =
- {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /*ob_size*/
- "ObjCMethod", /*tp_name*/
- sizeof(ObjCMethod), /*tp_basicsize*/
- 0, /*tp_itemsize*/
-
- /* methods */
- (destructor) ObjCMethod_dealloc, /*tp_dealloc*/
- (printfunc) 0, /*tp_print*/
- (getattrfunc) ObjCMethod_getattr, /*tp_getattr*/
- (setattrfunc) 0, /*tp_setattr*/
- (cmpfunc) 0, /*tp_compare*/
- (reprfunc) ObjCMethod_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- (hashfunc) 0, /*tp_hash*/
- (ternaryfunc) ObjCMethod_call, /*tp_call*/
- (reprfunc) 0, /*tp_str*/
- (getattrofunc) 0, /*tp_getattro*/
- (setattrofunc) 0, /*tp_setattro*/
-
- /* Space for future expansion */
- 0L,0L,
-
- "Wrapper around Objective-C selector" /* Documentation string */
- };
-
- /*
- ** Local Variables:
- ** change-log-default-name:"../ChangeLog.PyObjC"
- ** End:
- */
-