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: OC_PythonObject.m,v $
- * $Revision: 1.1.1.4 $
- * $Date: 1996/11/14 01:50:15 $
- *
- * Created Wed Sep 4 19:57:44 1996.
- */
-
- #include "objc_support.h"
- #include "abstract.h"
- #include "compile.h"
- #include <stdarg.h>
-
- #define CLASS_VERSION 0
-
- #ifndef MAX
- #define MAX(x,y) ({ unsigned int __x=(x), __y=(y); (__x > __y ? __x : __y); })
- #define MIN(x,y) ({ unsigned int __x=(x), __y=(y); (__x < __y ? __x : __y); })
- #endif
-
- @implementation OC_PythonObject
-
- + (void) initialize
- {
- if (self == [OC_PythonObject class])
- {
- [OC_PythonObject setVersion:CLASS_VERSION];
- }
- }
-
- + newWithObject:(PyObject *) obj
- {
- if (ObjCObject_Check (obj))
- return ((ObjCObject *) obj)->oc_object;
- else
- {
- id instance = [[self alloc] initWithObject:obj];
-
- #ifdef WITH_FOUNDATION
- [instance autorelease];
- #endif
-
- return instance;
- }
- }
-
- - initWithObject:(PyObject *) obj
- {
- [super init];
-
- #ifndef WITH_FOUNDATION
- Py_INCREF (obj);
- #endif
-
- pyObject = obj;
-
- return self;
- }
-
- #ifdef WITH_FOUNDATION
-
- - (void) retain
- {
- [super retain];
- Py_INCREF (pyObject);
- }
-
- - (oneway void) release
- {
- [super release];
- Py_DECREF (pyObject);
- }
-
- #else
-
- - copyFromZone:(NXZone *) zone
- {
- id copy;
-
- Py_INCREF (pyObject);
- copy = [super copyFromZone:zone];
-
- return copy;
- }
-
- - free
- {
- Py_DECREF (pyObject);
-
- return [super free];
- }
-
- #endif
-
- #define RETURN_RESULT(result) do { \
- if (result) \
- { \
- OC_PythonObject *ret = [[self class] newWithObject:result]; \
- \
- Py_DECREF (result); \
- return ret; \
- } \
- else \
- return nil; \
- } while(0)
-
- - doesNotRecognize:(SEL) aSelector
- {
- #define ERRORMSG " does not recognize -"
- const char *whoiam = NAMEOF(self);
- const char *selname = SELNAME(aSelector);
- char buffer[strlen (whoiam) + sizeof ERRORMSG + strlen (selname) + 1];
-
- strcpy (buffer, whoiam);
- strcat (buffer, ERRORMSG);
- strcat (buffer, selname);
- PyErr_SetString (ObjC_Error, buffer);
- return nil;
- }
-
- /*#F Check the argument count of the method/function @var{pymethod},
- returning the method itself if it matches @var{argcount}, NULL
- otherwise. */
- static inline PyObject *
- check_argcount (PyObject *pymethod, unsigned int argcount)
- {
- if (pymethod && (PyFunction_Check (pymethod) || PyMethod_Check (pymethod)))
- {
- PyCodeObject *func_code;
-
- if (PyMethod_Check (pymethod))
- {
- func_code = (PyCodeObject *) PyFunction_GetCode (PyMethod_Function (pymethod));
- argcount++; // for `self'
- }
- else
- func_code = (PyCodeObject *) PyFunction_GetCode (pymethod);
-
- if (func_code->co_argcount == argcount)
- return pymethod;
- }
-
- return NULL;
- }
-
- /*#F If the Python object @var{obj} implements a method whose name matches
- the Objective-C selector @var{aSelector} and accepts the correct number
- of arguments, return that method, otherwise NULL. */
- static PyObject *
- get_method_for_selector (PyObject *obj, SEL aSelector)
- {
- if (aSelector)
- {
- const char *meth_name = SELNAME(aSelector);
- int len = strlen (meth_name);
- char *pymeth_name;
- unsigned int argcount;
- PyObject *pymethod;
- register const char *p;
-
- for (argcount=0, p=meth_name; *p; p++)
- if (*p == ':')
- argcount++;
-
- pymeth_name = alloca (PYTHONIFIED_LENGTH(meth_name, len, argcount));
- #if PYTHONIFICATION_METHOD != WITH_BOTH
- pythonify_objc_message (meth_name, pymeth_name);
-
- pymethod = PyObject_GetAttrString (obj, pymeth_name);
- return check_argcount (pymethod, argcount);
- #else
- {
- PyObject *meth;
-
- pythonify_objc_message (meth_name, pymeth_name, PYTHONIFICATION_FIRST_TRY);
- pymethod = PyObject_GetAttrString (obj, pymeth_name);
- meth = check_argcount (pymethod, argcount);
- if (meth)
- return meth;
-
- #if PYTHONIFICATION_FIRST_TRY == WITH_DOUBLE_UNDERSCORE
- pythonify_objc_message (meth_name, pymeth_name, WITH_SINGLE_UNDERSCORE);
- #else
- pythonify_objc_message (meth_name, pymeth_name, WITH_DOUBLE_UNDERSCORE);
- #endif
- pymethod = PyObject_GetAttrString (obj, pymeth_name);
- meth = check_argcount (pymethod, argcount);
- if (meth)
- {
- if (Py_VerboseFlag)
- {
- char faster_name[200];
-
- fprintf (stderr, "PyObjC Warning: method `%s' matches `%s',\n\t", pymeth_name, meth_name);
-
- pythonify_objc_message (meth_name, faster_name, PYTHONIFICATION_FIRST_TRY);
-
- fprintf (stderr, "but `%s' would be faster.\n", faster_name);
- }
-
- return meth;
- }
- }
- #endif /* PYTHONIFICATION_METHOD != WITH_BOTH */
- }
- return NULL;
- }
-
- #ifdef WITH_FOUNDATION
- - (BOOL) respondsToSelector:(SEL) aSelector
- #else
- - (BOOL) respondsTo:(SEL) aSelector
- #endif
- {
- #ifdef WITH_FOUNDATION
- if ([super respondsToSelector:aSelector])
- #else
- if ([super respondsTo:aSelector])
- #endif
- return YES;
- else
- {
- PyObject *m = get_method_for_selector ([self object], aSelector);
-
- if (m)
- return YES;
- else
- {
- PyErr_Clear();
- return NO;
- }
- }
- }
-
- - forward:(SEL) aSelector :(marg_list) argFrame
- {
- PyObject *pymethod = get_method_for_selector ([self object], aSelector);
-
- if (pymethod)
- {
- PyObject *args = NULL;
- unsigned int i, argcount;
- PyCodeObject *func_code;
-
- if (PyMethod_Check (pymethod))
- {
- func_code = (PyCodeObject *) PyFunction_GetCode (PyMethod_Function (pymethod));
- argcount = func_code->co_argcount-1; // adjust for `self'
- }
- else
- {
- func_code = (PyCodeObject *) PyFunction_GetCode (pymethod);
- argcount = func_code->co_argcount;
- }
-
- args = PyTuple_New (argcount);
- if (args)
- {
- unsigned int offset = sizeof (id *) + sizeof (SEL *);
- PyObject *result;
-
- for (i=0; i<argcount; i++)
- {
- #ifdef GNU_RUNTIME
- /* XXX is this right? What about arguments in register? */
- id argument = *(id *) (argFrame->arg_ptr + offset + i*sizeof (id *));
- #else
- id argument = marg_getValue (argFrame, offset + i*sizeof (id *), id);
- #endif
- if ([argument isKindOf:[OC_PythonObject class]])
- {
- PyObject *pyarg = [argument object];
-
- Py_INCREF(pyarg);
- PyTuple_SET_ITEM (args, i, pyarg);
- }
- else
- {
- ObjCObject *pyarg = ObjCObject_new (argument);
-
- PyTuple_SET_ITEM (args, i, (PyObject *) pyarg);
- }
- }
-
- result = PyObject_CallObject (pymethod, args);
-
- Py_DECREF(args);
-
- RETURN_RESULT(result);
- }
- }
-
- return [self doesNotRecognize:aSelector];
- }
-
-
- // NUMBER PROTOCOL
-
- - (int) numberCheck
- {
- return PyNumber_Check ([self object]);
- }
-
- - (id <PythonObject>) numberAdd:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Add (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberSubtract:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Subtract (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberMultiply:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Multiply (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberDivide:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Divide (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberRemainder:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Remainder (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberDivmod:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Divmod (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberPower:(id <PythonObject>) o2
- :(id <PythonObject>) o3
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *pyo3 = [o3 object];
- PyObject *result = PyNumber_Power (pyo1, pyo2, pyo3);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberNegative
- {
- PyObject *pyo = [self object];
- PyObject *result = PyNumber_Negative (pyo);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberPositive
- {
- PyObject *pyo = [self object];
- PyObject *result = PyNumber_Positive (pyo);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberAbsolute
- {
- PyObject *pyo = [self object];
- PyObject *result = PyNumber_Absolute (pyo);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberInvert
- {
- PyObject *pyo = [self object];
- PyObject *result = PyNumber_Invert (pyo);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberLshift:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Lshift (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberRshift:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Rshift (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberAnd:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_And (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberXor:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Xor (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberOr:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PyNumber_Or (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberInt
- {
- PyObject *pyo = [self object];
- PyObject *result = PyNumber_Int (pyo);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberLong
- {
- PyObject *pyo = [self object];
- PyObject *result = PyNumber_Long (pyo);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) numberFloat
- {
- PyObject *pyo = [self object];
- PyObject *result = PyNumber_Float (pyo);
-
- RETURN_RESULT(result);
- }
-
- // SEQUENCE PROTOCOL
-
- - (int) sequenceCheck
- {
- return PySequence_Check ([self object]);
- }
-
- - (int) sequenceLength
- {
- return PySequence_Length ([self object]);
- }
-
- - (id <PythonObject>) sequenceConcat:(id <PythonObject>) o2
- {
- PyObject *pyo1 = [self object];
- PyObject *pyo2 = [o2 object];
- PyObject *result = PySequence_Concat (pyo1, pyo2);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) sequenceRepeat:(int) count
- {
- PyObject *pyo = [self object];
- PyObject *result = PySequence_Repeat (pyo, count);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) sequenceGetItem:(int) count
- {
- PyObject *pyo = [self object];
- PyObject *result = PySequence_GetItem (pyo, count);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) sequenceGetSliceFrom:(int) i1 to:(int) i2
- {
- PyObject *pyo = [self object];
- PyObject *result = PySequence_GetSlice (pyo, i1, i2);
-
- RETURN_RESULT(result);
- }
-
- - (int) sequenceSetItem:(int) i value:(id <PythonObject>) v
- {
-
- PyObject *pyo = [self object];
- PyObject *pyv = [v object];
-
- return PySequence_SetItem (pyo, i, pyv);
- }
-
- - (int) sequenceDelItem:(int) i
- {
-
- PyObject *pyo = [self object];
-
- return PySequence_DelItem (pyo, i);
- }
-
- - (int) sequenceSetSliceFrom:(int) i1
- to:(int) i2
- value:(id <PythonObject>) v
- {
- PyObject *pyo = [self object];
- PyObject *pyv = [v object];
-
- return PySequence_SetSlice (pyo, i1, i2, pyv);
- }
-
- - (int) sequenceDelSliceFrom:(int) i1
- to:(int) i2
- {
- PyObject *pyo = [self object];
-
- return PySequence_DelSlice (pyo, i1, i2);
- }
-
- - (id <PythonObject>) sequenceTuple
- {
- PyObject *pyo = [self object];
- PyObject *result = PySequence_Tuple (pyo);
-
- RETURN_RESULT(result);
- }
-
- - (int) sequenceCount:(id <PythonObject>) value
- {
- PyObject *pyo = [self object];
- PyObject *pyv = [value object];
-
- return PySequence_Count (pyo, pyv);
- }
-
- - (int) sequenceIn:(id <PythonObject>) value
- {
- PyObject *pyo = [self object];
- PyObject *pyv = [value object];
-
- return PySequence_In (pyo, pyv);
- }
-
- - (int) sequenceIndex:(id <PythonObject>) value
- {
- PyObject *pyo = [self object];
- PyObject *pyv = [value object];
-
- return PySequence_Index (pyo, pyv);
- }
-
- // CALLING PROTOCOL
-
- - (int) callableCheck
- {
- return PyCallable_Check ([self object]);
- }
-
- - (id <PythonObject>) callableCall:(id <PythonObject>) args
- {
- PyObject *pyo = [self object];
- PyObject *pyargs = [args object];
- PyObject *result = PyObject_CallObject (pyo, pyargs);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) callableCallFunction:(char *) format, ...
- {
- va_list va;
- PyObject *args;
- PyObject *result;
-
- va_start (va, format);
-
- if (format)
- args = Py_VaBuildValue (format, va);
- else
- args = PyTuple_New (0);
-
- va_end(va);
-
- if (! args)
- return nil;
-
- if(! PyTuple_Check (args))
- {
- PyObject *a = PyTuple_New (1);
-
- if (!a)
- return nil;
- PyTuple_SET_ITEM (a, 0, args);
-
- args = a;
- }
-
- result = PyObject_CallObject ([self object], args);
-
- Py_DECREF(args);
-
- RETURN_RESULT(result);
- }
-
- - (id <PythonObject>) callableCallMethod:(char *) m
- withArgs:(char *) format, ...
- {
- va_list va;
- PyObject *args;
- PyObject *method;
- PyObject *result;
-
- method = PyObject_GetAttrString ([self object], m);
- if (! method)
- {
- PyErr_SetString (PyExc_AttributeError, m);
- return nil;
- }
- else if (! PyCallable_Check (method))
- {
- PyErr_SetString(PyExc_TypeError,"call of non-callable attribute");
- return nil;
- }
-
- va_start (va, format);
-
- if (format)
- args = Py_VaBuildValue (format, va);
- else
- args = PyTuple_New (0);
-
- va_end(va);
-
- if (! args)
- return nil;
-
- if(! PyTuple_Check (args))
- {
- PyObject *a = PyTuple_New (1);
-
- if (!a)
- return nil;
- PyTuple_SET_ITEM (a, 0, args);
-
- args = a;
- }
-
- result = PyObject_CallObject (method, args);
-
- Py_DECREF(args);
-
- RETURN_RESULT(result);
- }
-
-
- // MAPPING PROTOCOL
-
- - (int) mappingCheck
- {
- return PyMapping_Check ([self object]);
- }
-
- - (int) mappingLength
- {
- return PyMapping_Length ([self object]);
- }
-
- - (int) mappingDelItemString:(char *) key
- {
- #ifndef PyMapping_DelItemString
- return PyDict_DelItemString ([self object], key);
- #else
- return PyMapping_DelItemString ([self object], key);
- #endif
- }
-
- - (int) mappingDelItem:(id <PythonObject>) key
- {
- #ifndef PyMapping_DelItem
- return PyDict_DelItem ([self object], [key object]);
- #else
- return PyMapping_DelItem ([self object], [key object]);
- #endif
- }
-
- - (int) mappingHasKeyString:(char *) key
- {
- return PyMapping_HasKeyString ([self object], key);
- }
-
- - (int) mappingHasKey:(id <PythonObject>) key
- {
- return PyMapping_HasKey ([self object], [key object]);
- }
-
- - (id <PythonObject>) mappingKeys
- {
- PyObject *pykeys = PyMapping_Keys ([self object]);
-
- RETURN_RESULT(pykeys);
- }
-
- - (id <PythonObject>) mappingItems
- {
- PyObject *pyitems = PyMapping_Items ([self object]);
-
- RETURN_RESULT(pyitems);
- }
-
- - (id <PythonObject>) mappingValues
- {
- PyObject *pyvalues = PyMapping_Values ([self object]);
-
- RETURN_RESULT(pyvalues);
- }
-
- - (id <PythonObject>) mappingGetItemString:(char *) key
- {
- PyObject *result = PyMapping_GetItemString ([self object], key);
-
- RETURN_RESULT(result);
- }
-
- - (int) mappingSetItemString:(char *) key value:(id <PythonObject>) value
- {
- return PyMapping_SetItemString ([self object], key, [value object]);
- }
-
-
- // PYTHON OBJECT PROTOCOL
-
- - (PyObject *) object
- {
- return pyObject;
- }
-
- - (int) print:(FILE *) fp flags:(int) flags
- {
- return PyObject_Print ([self object], fp, flags);
- }
-
- - (int) hasAttrString:(char *) attr_name
- {
- return PyObject_HasAttrString ([self object], attr_name);
- }
-
- - (id <PythonObject>) getAttrString:(char *) attr_name
- {
- PyObject *result = PyObject_GetAttrString ([self object], attr_name);
-
- RETURN_RESULT(result);
- }
-
- - (int) hasAttr:(id <PythonObject>) attr_name
- {
- [self notImplemented:_cmd];
- return 0;
- // XXX this is not yet implemented as of 1.4b3
- // return PyObject_HasAttr ([self object], [attr_name object]);
- }
-
- - (id <PythonObject>) getAttr:(id <PythonObject>) attr_name
- {
- PyObject *result = PyObject_GetAttr ([self object], [attr_name object]);
-
- RETURN_RESULT(result);
- }
-
- - (int) setAttrString:(char *) attr_name value:(id <PythonObject>) value
- {
- return PyObject_SetAttrString ([self object], attr_name, [value object]);
- }
-
- - (int) setAttr:(id <PythonObject>) attr_name value:(id <PythonObject>) value
- {
- return PyObject_SetAttr ([self object], [attr_name object], [value object]);
- }
-
- - (int) delAttrString:(char *) attr_name
- {
- return PyObject_DelAttrString ([self object], attr_name);
- }
-
- - (int) delAttr:(id <PythonObject>) attr_name
- {
- return PyObject_DelAttr ([self object], [attr_name object]);
- }
-
- - (int) cmp:(id <PythonObject>) o2 result:(int *) result
- {
- return PyObject_Cmp ([self object], [o2 object], result);
- }
-
- - (int) compare:(id <PythonObject>) o2
- {
- return PyObject_Compare ([self object], [o2 object]);
- }
-
- - (id <PythonObject>) repr
- {
- RETURN_RESULT(PyObject_Repr ([self object]));
- }
-
- - (id <PythonObject>) str
- {
- RETURN_RESULT(PyObject_Str ([self object]));
- }
-
- - (long) hash
- {
- return PyObject_Hash ([self object]);
- }
-
- - (int) isTrue
- {
- return PyObject_IsTrue ([self object]);
- }
-
- - (id <PythonObject>) type
- {
- RETURN_RESULT(PyObject_Type ([self object]));
- }
-
- - (int) length
- {
- return PyObject_Length ([self object]);
- }
-
- - (int) count
- {
- return PyObject_Length ([self object]);
- }
-
- - (id <PythonObject>) getItem:(id <PythonObject>) key
- {
- RETURN_RESULT(PyObject_GetItem ([self object], [key object]));
- }
-
- - (int) setItem:(id <PythonObject>) key value:(id <PythonObject>) v
- {
- return PyObject_SetItem ([self object],
- [key object],
- [v object]);
- }
-
- - (int) delItem:(id <PythonObject>) key
- {
- return PyObject_DelItem ([self object], [key object]);
- }
-
-
- @end /* OC_PythonObject class implementation */
-
- /*
- ** Local Variables:
- ** change-log-default-name:"../ChangeLog.PyObjC"
- ** End:
- */
-