1/*
2 * This file contains the code that is used to create proxy-classes for Python
3 * classes in the objective-C runtime.
4 */
5#include "pyobjc.h"
6
7#import <Foundation/NSInvocation.h>
8
9#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
10
11/*
12 * KVO was introduced in 10.3, but wasn't perfect and needs workarounds. Starting from 10.4 we can
13 * use KVO as-is without causing problems.
14 *
15 * Code to be removed when we no longer whish to support 10.3.
16 */
17
18#define TO_CHECK (0)		// Didn't check yet
19#define NO_KVO   (-1)		// No KVO available
20#define BROKEN_KVO (1)		// KVO available, but needs workaround
21#define OK_KVO (2)		// KVO available
22
23static int
24_KVOHackLevel(void) {
25	static int _checkedKVO = TO_CHECK;
26	if (_checkedKVO == TO_CHECK) {
27		if ([NSObject instancesRespondToSelector:@selector(willChangeValueForKey:)] &&
28			[NSObject instancesRespondToSelector:@selector(didChangeValueForKey:)]) {
29			_checkedKVO = BROKEN_KVO;
30			if ([NSObject instancesRespondToSelector:@selector(willChangeValueForKey:withSetMutation:usingObjects:)]) {
31				_checkedKVO = OK_KVO;
32			}
33		} else {
34			_checkedKVO = NO_KVO;
35		}
36	}
37	return _checkedKVO;
38}
39
40static BOOL
41_UseKVO(NSObject *self, NSString *key, BOOL isSet)
42{
43	int _checkedKVO = _KVOHackLevel();
44	NSNumber *n;
45	if (_checkedKVO == NO_KVO) {
46		return NO;
47	} else if (_checkedKVO == OK_KVO) {
48		return YES;
49	}
50	static NSMapTable* kvo_stack = nil;
51	if (kvo_stack == nil) {
52		kvo_stack = NSCreateMapTable(
53			PyObjCUtil_ObjCIdentityKeyCallBacks,
54			PyObjCUtil_ObjCValueCallBacks,
55			0);
56	}
57	// Hacks for Panther so that you don't get nested observations
58	NSMutableDictionary *kvoDict = (NSMutableDictionary *)NSMapGet(kvo_stack, (const void *)self);
59	if (!kvoDict) {
60		kvoDict = [[NSMutableDictionary alloc] initWithCapacity:0];
61		NSMapInsert(kvo_stack, (const void *)self, (const void *)kvoDict);
62		[kvoDict release];
63	}
64	if (isSet) {
65		int setCount = [(NSNumber *)[kvoDict objectForKey:key] intValue] + 1;
66		n = [[NSNumber alloc] initWithInt:setCount];
67		[kvoDict setValue:n forKey:key];
68		[n release];
69		if (setCount != 1) {
70			return NO;
71		}
72	} else {
73		int setCount = [(NSNumber *)[kvoDict objectForKey:key] intValue] - 1;
74		if (setCount != 0) {
75			n = [[NSNumber alloc] initWithInt:setCount];
76			[kvoDict setValue:n forKey:key];
77			[n release];
78			return NO;
79		} else {
80			[kvoDict removeObjectForKey:key];
81			if (![kvoDict count]) {
82				NSMapRemove(kvo_stack, (const void *)self);
83			}
84		}
85	}
86	return YES;
87}
88
89#endif
90
91/* Special methods for Python subclasses of Objective-C objects */
92static void object_method_finalize(
93		ffi_cif* cif,
94		void* retval,
95		void** args,
96		void* userarg);
97static void object_method_dealloc(
98		ffi_cif* cif,
99		void* retval,
100		void** args,
101		void* userarg);
102static void object_method_respondsToSelector(
103		ffi_cif* cif,
104		void* retval,
105		void** args,
106		void* userarg);
107static void object_method_methodSignatureForSelector(
108		ffi_cif* cif,
109		void* retval,
110		void** args,
111		void* userarg);
112static void object_method_forwardInvocation(
113		ffi_cif* cif,
114		void* retval,
115		void** args,
116		void* userarg);
117static void object_method_valueForKey_(
118		ffi_cif* cif,
119		void* retval,
120		void** args,
121		void* userarg);
122static void object_method_setValue_forKey_(
123		ffi_cif* cif,
124		void* retval,
125		void** args,
126		void* userarg);
127
128#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
129
130static void object_method_willOrDidChangeValueForKey_(
131		ffi_cif* cif,
132		void* retval,
133		void** args,
134		void* userarg);
135#endif
136
137static char copyWithZone_signature[132] = { '\0' };
138static void object_method_copyWithZone_(
139		ffi_cif* cif __attribute__((__unused__)),
140		void* resp,
141		void** args,
142		void* userdata);
143
144#define IDENT_CHARS "ABCDEFGHIJKLMNOPQSRTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789"
145
146/*
147 * Last step of the construction a python subclass of an objective-C class.
148 *
149 * Set reference to the python half in the objective-C half of the class.
150 *
151 * Return 0 on success, -1 on failure.
152 */
153int
154PyObjCClass_FinishClass(Class objc_class)
155{
156	PyObjC_Assert(objc_class != nil, -1);
157
158	objc_registerClassPair(objc_class);
159	return 0;
160}
161
162/*
163 * Call this when the python half of the class could not be created.
164 *
165 * Due to technical restrictions it is not allowed to unbuild a class that
166 * is already registered with the Objective-C runtime.
167 */
168int
169PyObjCClass_UnbuildClass(Class objc_class)
170{
171	PyObjC_Assert(objc_class != nil, -1);
172	PyObjC_Assert(objc_lookUpClass(class_getName(objc_class)) == nil, -1);
173
174	//objc_disposeClassPair(objc_class);
175	return 0;
176}
177
178/*
179 * The Python proxy for an object should not contain any state, even if
180 * the class is defined in Python. Therefore transfer all slots to the
181 * Objective-C class and add '__slots__ = ()' to the Python class.
182 */
183static int
184do_slots(PyObject* super_class, PyObject* clsdict)
185{
186	PyObject* slot_value;
187	PyObject* slots;
188	Py_ssize_t len, i;
189
190	slot_value = PyDict_GetItemString(clsdict, "__slots__");
191	if (slot_value == NULL) {
192		PyObject* v;
193
194		/* Add an __dict__ unless it is already there */
195		PyErr_Clear();
196
197		slot_value = PyTuple_New(0);
198		if (slot_value == NULL) {
199			return 0;
200		}
201
202		if (PyDict_SetItemString(clsdict, "__slots__", slot_value) < 0){
203			Py_DECREF(slot_value);
204			return -1;
205		}
206		Py_DECREF(slot_value);
207
208		if (PyObjCClass_DictOffset(super_class) != 0) {
209			/* We already have an __dict__ */
210			return 0;
211		}
212
213		v = PyObjCInstanceVariable_New("__dict__");
214		if (v == NULL) {
215			return -1;
216		}
217		((PyObjCInstanceVariable*)v)->type = PyObjCUtil_Strdup(@encode(PyObject*));
218		((PyObjCInstanceVariable*)v)->isSlot = 1;
219		if (PyDict_SetItemString(clsdict, "__dict__", v) < 0) {
220			Py_DECREF(v);
221			return -1;
222		}
223		Py_DECREF(v);
224
225		return 0;
226	}
227
228	slots = PySequence_Fast(slot_value, "__slots__ must be a sequence");
229	if (slots == NULL) {
230		return -1;
231	}
232
233	len = PySequence_Fast_GET_SIZE(slots);
234	for (i = 0; i < len; i++) {
235		PyObjCInstanceVariable* var;
236		slot_value = PySequence_Fast_GET_ITEM(slots, i);
237
238		if (!PyString_Check(slot_value)) {
239			PyErr_Format(PyExc_TypeError,
240				"__slots__ entry %" PY_FORMAT_SIZE_T
241				"d is not a string", i);
242			Py_DECREF(slots);
243			return -1;
244		}
245
246		var = (PyObjCInstanceVariable*)PyObjCInstanceVariable_New(
247				PyString_AS_STRING(slot_value));
248		if (var == NULL) {
249			Py_DECREF(slots);
250			return -1;
251		}
252		((PyObjCInstanceVariable*)var)->type = PyObjCUtil_Strdup(@encode(PyObject*));
253		((PyObjCInstanceVariable*)var)->isSlot = 1;
254
255		if (PyDict_SetItem(clsdict, slot_value, (PyObject*)var) < 0) {
256			Py_DECREF(slots);
257			Py_DECREF(var);
258			return -1;
259		}
260		Py_DECREF(var);
261	}
262	Py_DECREF(slots);
263
264	slot_value = PyTuple_New(0);
265	if (slot_value == NULL) {
266		return 0;
267	}
268	if (PyDict_SetItemString(clsdict, "__slots__", slot_value) < 0) {
269		Py_DECREF(slot_value);
270		return -1;
271	}
272	Py_DECREF(slot_value);
273	return 0;
274}
275
276/*
277 * Built a (pure Objective-C) subclass of base_class that defines our version
278 */
279
280static Class
281build_intermediate_class(Class base_class, char* name)
282{
283	Class intermediate_class = nil;
284	IMP closure;
285	PyObjCMethodSignature* methinfo = NULL;
286
287	if (copyWithZone_signature[0] == '\0') {
288		snprintf(copyWithZone_signature,
289			sizeof(copyWithZone_signature),
290			"@@:%s", @encode(NSZone*));
291	}
292
293	intermediate_class = objc_allocateClassPair(
294			base_class, strdup(name), 0);
295	if (intermediate_class == NULL) {
296		PyErr_NoMemory();
297		goto error_cleanup;
298	}
299
300	if ([base_class instancesRespondToSelector:@selector(copyWithZone:)]) {
301		methinfo = PyObjCMethodSignature_FromSignature(
302				copyWithZone_signature);
303		if (methinfo == NULL) goto error_cleanup;
304		closure = PyObjCFFI_MakeClosure(methinfo,
305				object_method_copyWithZone_, base_class);
306		Py_DECREF(methinfo); methinfo = NULL;
307		if (closure == NULL) goto error_cleanup;
308
309		preclass_addMethod(
310			intermediate_class,
311			@selector(copyWithZone:),
312			(IMP)closure,
313			copyWithZone_signature);
314	}
315	if ([base_class instancesRespondToSelector:@selector(mutableCopyWithZone:)]) {
316		methinfo = PyObjCMethodSignature_FromSignature(
317				copyWithZone_signature);
318		if (methinfo == NULL) goto error_cleanup;
319		closure = PyObjCFFI_MakeClosure(methinfo,
320				object_method_copyWithZone_, base_class);
321		Py_DECREF(methinfo); methinfo = NULL;
322		if (closure == NULL) goto error_cleanup;
323
324		preclass_addMethod(
325			intermediate_class,
326			@selector(mutableCopyWithZone:),
327			(IMP)closure,
328			copyWithZone_signature);
329	}
330
331	methinfo = PyObjCMethodSignature_FromSignature("v@:");
332	if (methinfo == NULL) goto error_cleanup;
333	closure = PyObjCFFI_MakeClosure(methinfo, object_method_dealloc,
334		base_class);
335	Py_DECREF(methinfo); methinfo = NULL;
336	if (closure == NULL) goto error_cleanup;
337
338	preclass_addMethod( intermediate_class, @selector(dealloc),
339			(IMP)closure, "v@:");
340
341	methinfo = PyObjCMethodSignature_FromSignature("v@:");
342	if (methinfo == NULL) goto error_cleanup;
343	closure = PyObjCFFI_MakeClosure(methinfo, object_method_finalize,
344		base_class);
345	Py_DECREF(methinfo); methinfo = NULL;
346	if (closure == NULL) goto error_cleanup;
347
348	preclass_addMethod( intermediate_class, @selector(finalize),
349			(IMP)closure, "v@:");
350
351	methinfo = PyObjCMethodSignature_FromSignature("@@:@");
352	if (methinfo == NULL) goto error_cleanup;
353	closure = PyObjCFFI_MakeClosure(methinfo, object_method_valueForKey_,
354		base_class);
355	Py_DECREF(methinfo); methinfo = NULL;
356	if (closure == NULL) goto error_cleanup;
357
358	preclass_addMethod(intermediate_class, @selector(valueForKey:),
359		(IMP)closure, "@@:@");
360	preclass_addMethod(intermediate_class, @selector(storedValueForKey:),
361		(IMP)closure, "@@:@");
362
363	methinfo = PyObjCMethodSignature_FromSignature("v@:@@");
364	if (methinfo == NULL) goto error_cleanup;
365	closure = PyObjCFFI_MakeClosure(methinfo, object_method_setValue_forKey_,
366		base_class);
367	Py_DECREF(methinfo); methinfo = NULL;
368	if (closure == NULL) goto error_cleanup;
369	preclass_addMethod(intermediate_class,
370		@selector(setValue:forKey:),        (IMP)closure, "v@:@@");
371	preclass_addMethod(intermediate_class,
372		@selector(takeStoredValue:forKey:), (IMP)closure, "v@:@@");
373	preclass_addMethod(intermediate_class,
374		@selector(takeValue:forKey:),       (IMP)closure, "v@:@@");
375
376
377	methinfo = PyObjCMethodSignature_FromSignature("c@::");
378	if (methinfo == NULL) goto error_cleanup;
379	closure = PyObjCFFI_MakeClosure(methinfo,
380		object_method_respondsToSelector,
381		base_class);
382	Py_DECREF(methinfo); methinfo = NULL;
383	if (closure == NULL) goto error_cleanup;
384	preclass_addMethod(intermediate_class,
385		@selector(respondsToSelector:),
386		(IMP)closure, "c@::");
387
388	methinfo = PyObjCMethodSignature_FromSignature("@@::");
389	if (methinfo == NULL) goto error_cleanup;
390	closure = PyObjCFFI_MakeClosure(methinfo,
391		object_method_methodSignatureForSelector,
392		base_class);
393	Py_DECREF(methinfo); methinfo = NULL;
394	if (closure == NULL) goto error_cleanup;
395	preclass_addMethod(intermediate_class,
396		@selector(methodSignatureForSelector:),
397		(IMP)closure, "@@::");
398
399	methinfo = PyObjCMethodSignature_FromSignature("v@:@");
400	if (methinfo == NULL) goto error_cleanup;
401	closure = PyObjCFFI_MakeClosure(methinfo,
402		object_method_forwardInvocation,
403		base_class);
404	Py_DECREF(methinfo); methinfo = NULL;
405	if (closure == NULL) goto error_cleanup;
406	preclass_addMethod(intermediate_class,
407		@selector(forwardInvocation:),
408		(IMP)closure, "v@:@");
409
410
411
412#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
413	if (_KVOHackLevel() == BROKEN_KVO) {
414		methinfo = PyObjCMethodSignature_FromSignature("v@:@");
415		if (methinfo == NULL) goto error_cleanup;
416		closure = PyObjCFFI_MakeClosure(methinfo, object_method_willOrDidChangeValueForKey_,
417			base_class);
418		Py_DECREF(methinfo); methinfo = NULL;
419		if (closure == NULL) goto error_cleanup;
420		preclass_addMethod(intermediate_class,
421			@selector(willChangeValueForKey:),
422			(IMP)closure, "v@:@");
423		preclass_addMethod(intermediate_class,
424			@selector(didChangeValueForKey:),
425			(IMP)closure, "v@:@");
426	}
427#endif
428
429	objc_registerClassPair(intermediate_class);
430
431	return (Class)intermediate_class;
432
433error_cleanup:
434	if (intermediate_class) {
435		objc_disposeClassPair(intermediate_class);
436	}
437	if (methinfo) {
438		Py_DECREF(methinfo);
439	}
440
441	return NULL;
442}
443
444
445
446/*
447 * First step of creating a python subclass of an objective-C class
448 *
449 * Returns NULL or the newly created objective-C class. 'class_dict' may
450 * be modified by this function.
451 *
452 * TODO:
453 * - Set 'sel_class' of PyObjCPythonSelector instances
454 * - This function complete ignores other base-classes, even though they
455 *   might override methods. Need to check the MRO documentation to check
456 *   if this is a problem.
457 * - It is a problem when the user tries to use mixins to define common
458 *   methods (like a NSTableViewDataSource mixin), this works but slowly
459 *   because this calls will always be resolved through forwardInvocation:
460 * - Add an 'override' flag that makes it possible to replace an existing
461 *   PyObjC class, feature request for the Python-IDE  (write class, run,
462 *   oops this doesn't work, rewrite class, reload and continue testing in
463 *   the running app)
464 */
465
466
467/* PyObjC uses a number of typecode descriptors that aren't available in
468 * the objc runtime.  Remove these from the type string (inline).
469 */
470static void tc2tc(char* buf)
471{
472	/* Skip pointer declarations and anotations */
473	for (;;) {
474		switch(*buf) {
475		case _C_PTR:
476		case _C_IN:
477		case _C_OUT:
478		case _C_INOUT:
479		case _C_ONEWAY:
480		case _C_CONST:
481			buf++;
482			break;
483		default:
484			goto exit;
485		}
486	}
487exit:
488
489	switch (*buf) {
490	case _C_NSBOOL:
491	case _C_CHAR_AS_INT:
492	case _C_CHAR_AS_TEXT:
493		*buf = _C_CHR;
494		break;
495
496	case _C_UNICHAR:
497		*buf = _C_SHT;
498		break;
499
500	case _C_STRUCT_B:
501		while (*buf != _C_STRUCT_E && *buf && *buf++ != '=') {
502		}
503		while (*buf && *buf != _C_STRUCT_E) {
504			if (*buf == '"') {
505				/* embedded field name */
506				buf = strchr(buf+1, '"');
507				if (buf == NULL) {
508					return;
509				}
510				buf++;
511			}
512			tc2tc(buf);
513			buf = (char*)PyObjCRT_SkipTypeSpec(buf);
514		}
515		break;
516
517	case _C_UNION_B:
518		while (*buf != _C_UNION_E && *buf && *buf++ != '=') {
519		}
520		while (*buf && *buf != _C_UNION_E) {
521			if (*buf == '"') {
522				/* embedded field name */
523				buf = strchr(buf+1, '"');
524				if (buf == NULL) {
525					return;
526				}
527				buf++;
528			}
529			tc2tc(buf);
530			buf = (char*)PyObjCRT_SkipTypeSpec(buf);
531		}
532		break;
533
534
535	case _C_ARY_B:
536		while (isdigit(*++buf));
537		tc2tc(buf);
538		break;
539	}
540}
541void PyObjC_RemoveInternalTypeCodes(char* buf)
542{
543	while(buf && *buf) {
544		tc2tc(buf);
545		buf = (char*)PyObjCRT_SkipTypeSpec(buf);
546	}
547}
548
549static BOOL same_signature(const char* sig1, const char* sig2)
550{
551	while (sig1 && *sig1 && sig2 && *sig2) {
552		const char* end1 = PyObjCRT_SkipTypeSpec(sig1);
553		const char* end2 = PyObjCRT_SkipTypeSpec(sig2);
554
555		/* Check for an invalid signature: */
556		if (end1 == NULL) return NO;
557		if (end2 == NULL) return NO;
558
559		const char* t1 = end1 - 1;
560		while (t1 != sig1 && isdigit(*t1)) {
561			t1--;
562		}
563		t1++;
564
565		const char* t2 = end2 - 1;
566		while (t2 != sig2 && isdigit(*t2)) {
567			t2--;
568		}
569		t2++;
570
571		if (t1 - sig1 != t2 - sig2) {
572			/* Elements don't have same size */
573			return NO;
574		}
575		if (strncmp(sig1, sig2, t1-sig1) != 0) {
576			/* Elements don't have same value */
577			return NO;
578		}
579		sig1 = end1;
580		sig2 = end2;
581	}
582
583	/* We reached the end of one of the signatures,
584	 * check that we reached both ends
585	 */
586	if (sig1 && *sig1) {
587		return NO;
588	}
589	if (sig2 && *sig2) {
590		return NO;
591	}
592	return YES;
593}
594
595Class
596PyObjCClass_BuildClass(Class super_class,  PyObject* protocols,
597		char* name, PyObject* class_dict, PyObject* meta_dict)
598{
599	PyObject*                key_list = NULL;
600	PyObject*                key = NULL;
601	PyObject*                value = NULL;
602	Py_ssize_t		 i;
603	Py_ssize_t		 key_count;
604	Py_ssize_t               protocol_count = 0;
605	int                      first_python_gen = 0;
606	Class		 	 new_class = NULL;
607	Class		 	 new_meta_class = NULL;
608	Class                    cur_class;
609	PyObject*                py_superclass = NULL;
610	Py_ssize_t               item_size;
611	int			 have_intermediate = 0;
612	int			 need_intermediate = 0;
613
614	if (!PyList_Check(protocols)) {
615		PyErr_Format(PyObjCExc_InternalError,
616			"protocol list not a python 'list' but '%s'",
617			protocols->ob_type->tp_name);
618		goto error_cleanup;
619	}
620	if (!PyDict_Check(class_dict)) {
621		PyErr_Format(PyObjCExc_InternalError,
622			"class dict not a python 'dict', but '%s'",
623			class_dict->ob_type->tp_name);
624		goto error_cleanup;
625	}
626	if (super_class == NULL) {
627		PyErr_SetString(PyObjCExc_InternalError,
628			"must have super_class");
629		goto error_cleanup;
630	}
631
632	if ((cur_class = objc_lookUpClass(name)) != NULL) {
633		/*
634		 * NOTE: we used to allow redefinition of a class if the
635		 * redefinition is in the same module. This code was removed
636		 * because that functionality isn't possible with the ObjC 2.0
637		 * runtime API.
638		 */
639
640		PyErr_Format(PyObjCExc_Error,
641			"%s is overriding existing Objective-C class",
642			name);
643		goto error_cleanup;
644	}
645	if (strspn(name, IDENT_CHARS) != strlen(name)) {
646		PyErr_Format(PyObjCExc_Error, "'%s' not a valid name", name);
647		goto error_cleanup;
648	}
649
650	PyDict_SetItemString(class_dict, "__objc_python_subclass__", Py_True);
651
652	py_superclass = PyObjCClass_New(super_class);
653	if (py_superclass == NULL) return NULL;
654
655	/* We must override copyWithZone: for python classes because the
656	 * refcounts of python slots might be off otherwise. Yet it should
657	 * be possible to override copyWithZone: in those classes.
658	 *
659	 * The solution: introduce an intermediate class that contains our
660	 * implementation of copyWithZone:. This intermediate class is only
661	 * needed when (1) the superclass implements copyWithZone: and (2)
662	 * the python subclass overrides that method.
663	 *
664	 * The same issue is present with a number of other methods.
665	 */
666
667	need_intermediate = 0;
668
669	if (PyDict_GetItemString(class_dict, "copyWithZone_") == NULL) {
670		PyErr_Clear();
671	} else {
672		if ([super_class instancesRespondToSelector:@selector(copyWithZone:)]) {
673			need_intermediate = 1;
674		}
675	}
676	if (PyDict_GetItemString(class_dict, "mutableCopyWithZone_") == NULL) {
677		PyErr_Clear();
678	} else {
679		if ([super_class instancesRespondToSelector:@selector(mutableCopyWithZone:)]) {
680			need_intermediate = 1;
681		}
682	}
683
684	if (PyDict_GetItemString(class_dict, "dealloc") == NULL) {
685		PyErr_Clear();
686	} else {
687		need_intermediate = 1;
688	}
689	if (PyDict_GetItemString(class_dict, "finalize") == NULL) {
690		PyErr_Clear();
691	} else {
692		need_intermediate = 1;
693	}
694	if (PyDict_GetItemString(class_dict, "valueForKey_") == NULL) {
695		PyErr_Clear();
696	} else {
697		need_intermediate = 1;
698	}
699	if (PyDict_GetItemString(class_dict, "storedValueForKey_") == NULL) {
700		PyErr_Clear();
701	} else {
702		need_intermediate = 1;
703	}
704	if (PyDict_GetItemString(class_dict, "setValue_forKey_") == NULL) {
705		PyErr_Clear();
706	} else {
707		need_intermediate = 1;
708	}
709	if (PyDict_GetItemString(class_dict, "takeValue_forKey_") == NULL) {
710		PyErr_Clear();
711	} else {
712		need_intermediate = 1;
713	}
714	if (PyDict_GetItemString(class_dict, "takeStoredValue_forKey_") == NULL) {
715		PyErr_Clear();
716	} else {
717		need_intermediate = 1;
718	}
719	if (PyDict_GetItemString(class_dict, "respondsToSelector_") == NULL) {
720		PyErr_Clear();
721	} else {
722		need_intermediate = 1;
723	}
724	if (PyDict_GetItemString(class_dict, "instancesRespondToSelector_") == NULL) {
725		PyErr_Clear();
726	} else {
727		need_intermediate = 1;
728	}
729
730	if (PyDict_GetItemString(class_dict, "methodSignatureForSelector_") == NULL) {
731		PyErr_Clear();
732	} else {
733		need_intermediate = 1;
734	}
735	if (PyDict_GetItemString(class_dict, "forwardInvocation_") == NULL) {
736		PyErr_Clear();
737	} else {
738		need_intermediate = 1;
739	}
740
741#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
742	if (_KVOHackLevel() == BROKEN_KVO) {
743		if (PyDict_GetItemString(class_dict, "willChangeValueForKey_") == NULL) {
744			PyErr_Clear();
745		} else {
746			need_intermediate = 1;
747		}
748		if (PyDict_GetItemString(class_dict, "didChangeValueForKey_") == NULL) {
749			PyErr_Clear();
750		} else {
751			need_intermediate = 1;
752		}
753	}
754#endif
755
756	if (!PyObjCClass_HasPythonImplementation(py_superclass) && need_intermediate) {
757		Class intermediate_class;
758		char  buf[1024];
759
760		have_intermediate = 1;
761
762		snprintf(buf, 1024, "_PyObjCCopying_%s", class_getName(super_class));
763		intermediate_class = objc_lookUpClass(buf);
764		if (intermediate_class == NULL) {
765			intermediate_class = build_intermediate_class(
766					super_class, buf);
767			if (intermediate_class == NULL) goto error_cleanup;
768		}
769		Py_DECREF(py_superclass);
770
771		super_class = intermediate_class;
772		py_superclass = PyObjCClass_New(super_class);
773		if (py_superclass == NULL) return NULL;
774	}
775
776
777	if (do_slots(py_superclass, class_dict) < 0) {
778		goto error_cleanup;
779	}
780
781
782
783	if (!PyObjCClass_HasPythonImplementation(py_superclass)) {
784		/*
785		 * This class has a super_class that is pure objective-C
786		 * We'll add some instance variables and methods that are
787		 * needed for the correct functioning of the class.
788		 *
789		 * See the code below the next loop.
790		 */
791		first_python_gen = 1;
792	}
793
794
795	key_list = PyDict_Keys(class_dict);
796	if (key_list == NULL) {
797		goto error_cleanup;
798	}
799
800	key_count = PyList_Size(key_list);
801	if (PyErr_Occurred()) {
802		Py_DECREF(key_list);
803		goto error_cleanup;
804	}
805
806	/* Allocate the class as soon as possible, for new selector objects */
807	new_class = objc_allocateClassPair(super_class, name, 0);
808	if (new_class == 0) {
809		PyErr_Format(PyObjCExc_Error,
810			"Cannot allocateClassPair for %s", name);
811		goto error_cleanup;
812	}
813
814	new_meta_class = object_getClass(new_class);
815
816	/* 0th round: protocols */
817	protocol_count = PyList_Size(protocols);
818	if (protocol_count > 0) {
819		for (i=0; i < protocol_count; i++) {
820			PyObject *wrapped_protocol;
821			wrapped_protocol = PyList_GET_ITEM(protocols, i);
822			if (!PyObjCFormalProtocol_Check(wrapped_protocol)) {
823				continue;
824			}
825
826			if (!preclass_addProtocol(new_class,
827					PyObjCFormalProtocol_GetProtocol(wrapped_protocol))) {
828				goto error_cleanup;
829			}
830		}
831	}
832	if (PyErr_Occurred()) {
833		goto error_cleanup;
834	}
835
836	/* First round, count new instance-vars and check for overridden
837	 * methods.
838	 */
839	for (i = 0; i < key_count; i++) {
840		key = PyList_GET_ITEM(key_list, i);
841#if 0
842		if (PyErr_Occurred()) {
843			PyErr_SetString(PyObjCExc_InternalError,
844				"PyObjCClass_BuildClass: "
845				"Cannot fetch key in keylist");
846			goto error_cleanup;
847		}
848#endif
849
850		value = PyDict_GetItem(class_dict, key);
851		if (value == NULL) {
852			PyErr_SetString(PyObjCExc_InternalError,
853				"PyObjCClass_BuildClass: "
854				"Cannot fetch item in keylist");
855			goto error_cleanup;
856		}
857
858		if (PyObjCInstanceVariable_Check(value)) {
859			if (PyObjCInstanceVariable_SetName(value, key) == -1) {
860				goto error_cleanup;
861			}
862			if (class_getInstanceVariable(super_class,
863			    ((PyObjCInstanceVariable*)value)->name) != NULL) {
864				PyErr_Format(PyObjCExc_Error,
865					"a superclass already has an instance "
866					"variable with this name: %s",
867					((PyObjCInstanceVariable*)value)->name);
868				goto error_cleanup;
869			}
870
871			if (((PyObjCInstanceVariable*)value)->isSlot) {
872				item_size = sizeof(PyObject**);
873			} else {
874				item_size = PyObjCRT_SizeOfType(
875					((PyObjCInstanceVariable*)value)->type);
876			}
877			if (item_size == -1) goto error_cleanup;
878
879
880		} else if (PyObjCNativeSelector_Check(value)) {
881			char methType = '-';
882			if (PyObjCSelector_IsClassMethod(value)) {
883				methType = '+';
884			}
885			PyErr_Format(PyExc_TypeError,
886				"native selector %c%s of %s",
887				methType,
888				sel_getName(PyObjCSelector_GetSelector(value)),
889				class_getName(PyObjCSelector_GetClass(value)));
890			goto error_cleanup;
891
892		} else if (PyObjCSelector_Check(value)) {
893			PyObjCSelector* sel = (PyObjCSelector*)value;
894
895			/* If it already has a sel_class, create a copy */
896#if 0
897			if (sel->sel_class != NULL) {
898				value = PyObjCSelector_Copy(value);
899				if (value == NULL) goto error_cleanup;
900				if (PyDict_SetItem(class_dict, key, value) == -1) {
901					Py_DECREF(value);
902					goto error_cleanup;
903				}
904				Py_DECREF(value);
905				sel = (PyObjCSelector*)value;
906			}
907#endif
908
909			/* Set sel_class */
910			sel->sel_class = new_class;
911
912		} else if (
913				PyMethod_Check(value)
914			     || PyFunction_Check(value)
915			     || PyObject_TypeCheck(value, &PyClassMethod_Type)){
916
917			PyObject* pyname;
918			char*     ocname;
919			pyname = key;
920			if (pyname == NULL) continue;
921
922			ocname = PyString_AS_STRING(pyname);
923
924			if (ocname[0] == '_' && ocname[1] == '_') {
925				/* Skip special methods (like __getattr__) to
926				 * avoid confusing type().
927				 */
928				continue;
929			}
930
931			value = PyObjCSelector_FromFunction(
932					pyname,
933					value,
934					py_superclass,
935					protocols);
936			if (value == NULL) goto error_cleanup;
937
938			if (!PyObjCSelector_Check(value)) {
939				Py_DECREF(value);
940				continue;
941			}
942
943			((PyObjCSelector*)value)->sel_class = new_class;
944
945			if (PyDict_SetItem(class_dict, key, value) < 0) {
946				Py_DECREF(value); value = NULL;
947				goto error_cleanup;
948			}
949			Py_DECREF(value); value = NULL;
950		}
951	}
952
953	/* Allocate space for the new instance variables and methods */
954	if (first_python_gen) {
955		/* Our parent is a pure Objective-C class, add our magic
956		 * methods and variables
957		 */
958
959		PyObject* sel;
960		IMP closure;
961		PyObjCMethodSignature* methinfo;
962
963#		define METH(pyname, selector, types, imp) 		\
964		        methinfo = PyObjCMethodSignature_FromSignature(types); \
965			if (methinfo == NULL) goto error_cleanup; \
966			closure = PyObjCFFI_MakeClosure(methinfo, imp, \
967					super_class); \
968			Py_DECREF(methinfo); methinfo = NULL; \
969			if (closure == NULL) goto error_cleanup; \
970			preclass_addMethod(new_class, selector, \
971					closure, types); \
972			sel = PyObjCSelector_NewNative(new_class, \
973				selector,  types, 0);			\
974			if (sel == NULL) goto error_cleanup;		\
975			PyDict_SetItemString(class_dict, pyname, sel);	\
976			Py_DECREF(sel)
977
978		if (!have_intermediate) {
979			METH(
980				"dealloc",
981				@selector(dealloc),
982				"v@:",
983				object_method_dealloc);
984			METH(
985				"finalize",
986				@selector(finalize),
987				"v@:",
988				object_method_finalize);
989			METH(
990				"storedValueForKey_",
991				@selector(storedValueForKey:),
992				"@@:@",
993				object_method_valueForKey_);
994			METH(
995				"valueForKey_",
996				@selector(valueForKey:),
997				"@@:@",
998				object_method_valueForKey_);
999			METH(
1000				"takeStoredValue_forKey_",
1001				@selector(takeStoredValue:forKey:),
1002				"v@:@@",
1003				object_method_setValue_forKey_);
1004			METH(
1005				"takeValue_forKey_",
1006				@selector(takeValue:forKey:),
1007				"v@:@@",
1008				object_method_setValue_forKey_);
1009			METH(
1010				"setValue_forKey_",
1011				@selector(setValue:forKey:),
1012				"v@:@@",
1013				object_method_setValue_forKey_);
1014
1015			METH(
1016				"forwardInvocation_",
1017				@selector(forwardInvocation:),
1018				"v@:@",
1019				object_method_forwardInvocation);
1020			METH(
1021				"methodSignatureForSelector_",
1022				@selector(methodSignatureForSelector:),
1023				"@@::",
1024				object_method_methodSignatureForSelector);
1025			METH(
1026				"respondsToSelector",
1027				@selector(respondsToSelector:),
1028				"c@::",
1029				object_method_respondsToSelector);
1030
1031#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
1032			if (_KVOHackLevel() == BROKEN_KVO) {
1033				METH(
1034					"willChangeValueForKey_",
1035					@selector(willChangeValueForKey:),
1036					"v@:@",
1037					object_method_willOrDidChangeValueForKey_);
1038				METH(
1039					"didChangeValueForKey_",
1040					@selector(didChangeValueForKey:),
1041					"v@:@",
1042					object_method_willOrDidChangeValueForKey_);
1043			}
1044#endif
1045		}
1046
1047
1048		if (!have_intermediate && [super_class instancesRespondToSelector:@selector(copyWithZone:)]) {
1049			if (copyWithZone_signature[0] == '\0') {
1050				snprintf(copyWithZone_signature,
1051					sizeof(copyWithZone_signature),
1052					"@@:%s", @encode(NSZone*));
1053			}
1054
1055			METH(
1056				"copyWithZone_",
1057				@selector(copyWithZone:),
1058				copyWithZone_signature,
1059				object_method_copyWithZone_);
1060		}
1061		if (!have_intermediate && [super_class instancesRespondToSelector:@selector(mutableCopyWithZone:)]) {
1062			if (copyWithZone_signature[0] == '\0') {
1063				snprintf(copyWithZone_signature,
1064					sizeof(copyWithZone_signature),
1065					"@@:%s", @encode(NSZone*));
1066			}
1067
1068			METH(
1069				"mutableCopyWithZone_",
1070				@selector(copyWithZone:),
1071				copyWithZone_signature,
1072				object_method_copyWithZone_);
1073		}
1074#undef		METH
1075	}
1076
1077	for (i = 0; i < key_count; i++) {
1078		key = PyList_GetItem(key_list, i);
1079		if (key == NULL) {
1080			PyErr_SetString(PyObjCExc_InternalError,
1081				"PyObjCClass_BuildClass: "
1082				"Cannot fetch key in keylist");
1083			goto error_cleanup;
1084		}
1085
1086		value = PyDict_GetItem(class_dict, key);
1087		if (value == NULL)  {
1088			PyErr_SetString(PyObjCExc_InternalError,
1089				"PyObjCClass_BuildClass: "
1090				"Cannot fetch item in keylist");
1091			goto error_cleanup;
1092		}
1093
1094		if (PyObjCInstanceVariable_Check(value)) {
1095			char* type;
1096			size_t size;
1097			size_t align;
1098
1099
1100			if (PyObjCInstanceVariable_IsSlot(value)) {
1101				type = @encode(PyObject*);
1102				size = sizeof(PyObject*);
1103			} else {
1104				type = PyObjCInstanceVariable_GetType(value);
1105				size = PyObjCRT_SizeOfType(type);
1106			}
1107			align = PyObjCRT_AlignOfType(type);
1108
1109			if (!preclass_addIvar(new_class,
1110				PyObjCInstanceVariable_GetName(value),
1111				size,
1112				align,
1113				type
1114				)) {
1115
1116				goto error_cleanup;
1117			}
1118
1119		} else if (PyObjCSelector_Check(value)) {
1120			PyObjCSelector* sel = (PyObjCSelector*)value;
1121			Method	      meth;
1122			int           is_override = 0;
1123			Class	      cls;
1124			IMP	      imp;
1125
1126			/* Check if the 'key' is the name as the python
1127			 * representation of our selector. If not: add the
1128			 * python representation of our selector to the
1129			 * dict as well to ensure that the ObjC interface works
1130			 * from Python as well.
1131			 *
1132			 * NOTE: This also allows one to add both a class
1133			 * and instance method for the same selector in one
1134			 * generation.
1135			 */
1136			char buf[1024];
1137			PyObject* pyname = PyString_FromString(
1138				PyObjC_SELToPythonName(sel->sel_selector, buf, sizeof(buf)));
1139			if (pyname == NULL) goto error_cleanup;
1140			int shouldCopy = PyObject_RichCompareBool(pyname, key, Py_EQ);
1141			if (shouldCopy == -1) goto error_cleanup;
1142
1143
1144			if (sel->sel_flags & PyObjCSelector_kCLASS_METHOD) {
1145				meth = class_getClassMethod(super_class,
1146					sel->sel_selector);
1147				if (meth) {
1148					is_override = 1;
1149
1150					if (!same_signature(method_getTypeEncoding(meth),
1151						sel->sel_native_signature)) {
1152
1153						PyObject* repr = PyObject_Repr((PyObject*)sel);
1154						if (repr == NULL) goto error_cleanup;
1155						PyErr_Format(PyObjCExc_BadPrototypeError,
1156							"%s has signature that is not compatible with super-class",
1157							PyString_AsString(repr));
1158						Py_DECREF(repr);
1159						goto error_cleanup;
1160					}
1161				}
1162				cls = new_meta_class;
1163
1164				/* Class method: the value should be in the
1165				 * metadict instead of the regular dict.
1166				 * Make it so.
1167				 */
1168				if (shouldCopy) {
1169					if (PyDict_SetItem(meta_dict, pyname, value) == -1) {
1170						Py_DECREF(pyname);
1171						goto error_cleanup;
1172					}
1173				}
1174				Py_DECREF(pyname);
1175
1176				if (PyDict_SetItem(meta_dict, key, value) == -1)
1177					goto error_cleanup;
1178				if (PyDict_DelItem(class_dict, key) == -1)
1179					goto error_cleanup;
1180
1181
1182
1183			} else {
1184				meth = class_getInstanceMethod(super_class,
1185					sel->sel_selector);
1186				if (meth) {
1187					is_override = 1;
1188					if (!same_signature(method_getTypeEncoding(meth),
1189						sel->sel_native_signature)) {
1190
1191						PyObject* repr = PyObject_Repr((PyObject*)sel);
1192						if (repr == NULL) goto error_cleanup;
1193						PyErr_Format(PyObjCExc_BadPrototypeError,
1194							"%s has signature that is not compatible with super-class",
1195							PyString_AsString(repr));
1196						Py_DECREF(repr);
1197						goto error_cleanup;
1198					}
1199				}
1200				cls = new_class;
1201
1202				if (shouldCopy) {
1203					if (PyDict_SetItem(class_dict, pyname, value) == -1) {
1204						Py_DECREF(pyname);
1205						goto error_cleanup;
1206					}
1207				}
1208				Py_DECREF(pyname);
1209			}
1210
1211			if (is_override) {
1212				imp = PyObjC_MakeIMP(cls, super_class, value, value);
1213			} else  {
1214				imp = PyObjC_MakeIMP(cls, nil, value, value);
1215			}
1216			if (imp == NULL) {
1217				goto error_cleanup;
1218			}
1219
1220			if (!preclass_addMethod(cls, sel->sel_selector, imp,
1221						sel->sel_native_signature)) {
1222				goto error_cleanup;
1223			}
1224
1225			if (sel->sel_class == NULL) {
1226				sel->sel_class = new_class;
1227			}
1228		} /* XXX: else if (PyObjCIMP_Check(value)) */
1229	}
1230	Py_DECREF(key_list);
1231	key_list = NULL;
1232
1233	Py_XDECREF(py_superclass); py_superclass = NULL;
1234
1235	if (PyDict_DelItemString(class_dict, "__dict__") < 0) {
1236		PyErr_Clear();
1237	}
1238
1239	/*
1240	 * NOTE: Class is not registered yet, we do that as lately as possible
1241	 * because it is impossible to remove the registration from the
1242	 * objective-C runtime (at least on MacOS X).
1243	 */
1244	return new_class;
1245
1246error_cleanup:
1247	Py_XDECREF(py_superclass);
1248
1249	if (key_list) {
1250		Py_DECREF(key_list);
1251		key_list = NULL;
1252	}
1253
1254	if (new_class) {
1255		objc_disposeClassPair(new_class);
1256	}
1257
1258	return NULL;
1259}
1260
1261/*
1262 * Below here are implementations of various methods needed to correctly
1263 * subclass Objective-C classes from Python.
1264 *
1265 * These are added to the new Objective-C class by  PyObjCClass_BuildClass (but
1266 * only if the super_class is a 'pure' objective-C class)
1267 *
1268 * NOTE:
1269 * - These functions will be used as methods, but as far as the compiler
1270 *   knows these are normal functions. You cannot use [super call]s here.
1271 */
1272
1273
1274static void
1275free_ivars(id self, PyObject* volatile cls )
1276{
1277	/* Free all instance variables introduced through python */
1278	volatile Ivar var;
1279
1280	var = class_getInstanceVariable(PyObjCClass_GetClass(cls), "__dict__");
1281	if (var != NULL) {
1282		ptrdiff_t offset = ivar_getOffset(var);
1283		Py_XDECREF(*(PyObject**)(((char*)self) + offset));
1284		*(PyObject**)(((char*)self) + offset) = NULL;
1285	}
1286
1287	while (cls != NULL) {
1288		Class objcClass = PyObjCClass_GetClass(cls);
1289		PyObject* clsDict;
1290		PyObject* clsValues;
1291		PyObject* o;
1292		volatile Py_ssize_t i;
1293		Py_ssize_t len;
1294
1295		if (objcClass == nil) break;
1296
1297
1298		clsDict = PyObject_GetAttrString(cls, "__dict__");
1299		if (clsDict == NULL) {
1300			PyErr_Clear();
1301			break;
1302		}
1303
1304		/* Class.__dict__ is a dictproxy, which is not a dict and
1305		 * therefore PyDict_Values doesn't work.
1306		 */
1307		clsValues = PyObject_CallMethod(clsDict, "values", NULL);
1308		Py_DECREF(clsDict);
1309		if (clsValues == NULL) {
1310			PyErr_Clear();
1311			break;
1312		}
1313
1314		len = PyList_Size(clsValues);
1315		/* Check type */
1316		for (i = 0; i < len; i++) {
1317			PyObjCInstanceVariable* iv;
1318
1319			o = PyList_GET_ITEM(clsValues, i);
1320
1321			if (o == NULL) continue;
1322			if (!PyObjCInstanceVariable_Check(o)) continue;
1323
1324			iv = ((PyObjCInstanceVariable*)o);
1325
1326			if (iv->isOutlet) continue;
1327			if (strcmp(iv->type, "@") != 0 && strcmp(iv->type, @encode(PyObject*)) != 0) continue;
1328
1329			var = class_getInstanceVariable(objcClass, iv->name);
1330			if (var == NULL) continue;
1331
1332			if (iv->isSlot) {
1333				Py_XDECREF(*(PyObject**)(((char*)self) +
1334					ivar_getOffset(var)));
1335				(*(PyObject**)(((char*)self) +
1336					ivar_getOffset(var))) = NULL;
1337			} else {
1338				PyObjC_DURING
1339					[*(id*)(((char*)self) + ivar_getOffset(var)) autorelease];
1340
1341				PyObjC_HANDLER
1342					NSLog(@"ignoring exception %@ in destructor",
1343						localException);
1344
1345				PyObjC_ENDHANDLER
1346				*(id*)(((char*)self) + ivar_getOffset(var)) = NULL;
1347			}
1348		}
1349
1350		Py_DECREF(clsValues);
1351
1352		o = PyObject_GetAttrString(cls, "__bases__");
1353		if (o == NULL) {
1354			PyErr_Clear();
1355			cls = NULL;
1356		}  else if (PyTuple_Size(o) == 0) {
1357			PyErr_Clear();
1358			cls = NULL;
1359			Py_DECREF(o);
1360		} else {
1361			cls = PyTuple_GET_ITEM(o, 0);
1362			if (cls == (PyObject*)&PyObjCClass_Type) {
1363				cls = NULL;
1364			}
1365			Py_DECREF(o);
1366		}
1367	}
1368}
1369
1370/* -finalize */
1371static void
1372object_method_finalize(
1373		ffi_cif* cif __attribute__((__unused__)),
1374		void* retval __attribute__((__unused__)),
1375		void** args,
1376		void* userdata)
1377{
1378	id self = *(id*)(args[0]);
1379	SEL _meth = *(SEL*)(args[1]);
1380
1381	struct objc_super spr;
1382	PyObject* obj;
1383	PyObject* delmethod;
1384	PyObject* cls;
1385	PyObject* ptype, *pvalue, *ptraceback;
1386
1387	PyObjC_BEGIN_WITH_GIL
1388
1389		PyErr_Fetch(&ptype, &pvalue, &ptraceback);
1390
1391		cls = PyObjCClass_New(object_getClass(self));
1392
1393		delmethod = PyObjCClass_GetDelMethod(cls);
1394		if (delmethod != NULL) {
1395			PyObject* s = _PyObjCObject_NewDeallocHelper(self);
1396			obj = PyObject_CallFunction(delmethod, "O", s);
1397			_PyObjCObject_FreeDeallocHelper(s);
1398			if (obj == NULL) {
1399				PyErr_WriteUnraisable(delmethod);
1400			} else {
1401				Py_DECREF(obj);
1402			}
1403			Py_DECREF(delmethod);
1404		}
1405
1406		free_ivars(self, cls);
1407
1408		PyErr_Restore(ptype, pvalue, ptraceback);
1409
1410	PyObjC_END_WITH_GIL
1411
1412	objc_superSetClass(spr, (Class)userdata);
1413	objc_superSetReceiver(spr, self);
1414
1415	objc_msgSendSuper(&spr, _meth);
1416}
1417
1418/* -dealloc */
1419static void
1420object_method_dealloc(
1421		ffi_cif* cif __attribute__((__unused__)),
1422		void* retval __attribute__((__unused__)),
1423		void** args,
1424		void* userdata)
1425{
1426	id self = *(id*)(args[0]);
1427	SEL _meth = *(SEL*)(args[1]);
1428
1429	struct objc_super spr;
1430	PyObject* obj;
1431	PyObject* delmethod;
1432	PyObject* cls;
1433	PyObject* ptype, *pvalue, *ptraceback;
1434
1435	PyObjC_BEGIN_WITH_GIL
1436
1437		PyErr_Fetch(&ptype, &pvalue, &ptraceback);
1438
1439		cls = PyObjCClass_New(object_getClass(self));
1440
1441		delmethod = PyObjCClass_GetDelMethod(cls);
1442		if (delmethod != NULL) {
1443			PyObject* s = _PyObjCObject_NewDeallocHelper(self);
1444			obj = PyObject_CallFunction(delmethod, "O", s);
1445			_PyObjCObject_FreeDeallocHelper(s);
1446			if (obj == NULL) {
1447				PyErr_WriteUnraisable(delmethod);
1448			} else {
1449				Py_DECREF(obj);
1450			}
1451			Py_DECREF(delmethod);
1452		}
1453
1454		free_ivars(self, cls);
1455
1456		PyErr_Restore(ptype, pvalue, ptraceback);
1457
1458	PyObjC_END_WITH_GIL
1459
1460	objc_superSetClass(spr, (Class)userdata);
1461	objc_superSetReceiver(spr, self);
1462
1463	objc_msgSendSuper(&spr, _meth);
1464}
1465
1466/* -copyWithZone:(NSZone*)zone */
1467static void
1468object_method_copyWithZone_(
1469		ffi_cif* cif __attribute__((__unused__)),
1470		void* resp,
1471		void** args,
1472		void* userdata)
1473{
1474	id self = *(id*)args[0];
1475	id copy;
1476	SEL _meth = *(SEL*)args[1];
1477	NSZone* zone = *(NSZone**)args[2];
1478	Class cls;
1479
1480	struct objc_super spr;
1481	PyGILState_STATE state;
1482
1483	/* Ask super to create a copy */
1484
1485	objc_superSetClass(spr, (Class)userdata);
1486	objc_superSetReceiver(spr, self);
1487	copy = objc_msgSendSuper(&spr, _meth, zone);
1488
1489	if (copy == nil) {
1490		*(id*)resp = nil;
1491		return;
1492	}
1493
1494	state = PyGILState_Ensure();
1495
1496	cls = object_getClass(self);
1497	while (cls != (Class)userdata) {
1498		unsigned ivarCount, i;
1499		Ivar* ivarList = class_copyIvarList(cls, &ivarCount);
1500
1501		for (i = 0; i < ivarCount; i++) {
1502			Ivar v = ivarList[i];
1503			const char*  typestr;
1504			ptrdiff_t offset;
1505			PyObject** p;
1506
1507			typestr = ivar_getTypeEncoding(v);
1508			offset  = ivar_getOffset(v);
1509
1510			if (strcmp(typestr, @encode(PyObject*))!=0)
1511				continue;
1512
1513			/* A PyObject, increase it's refcount */
1514			p = (PyObject**)(((char*)copy)+offset);
1515			if (*p == NULL) continue;
1516			if (strcmp(ivar_getName(v), "__dict__") == 0) {
1517				/* copy __dict__ */
1518				*p = PyDict_Copy(*p);
1519				if (*p == NULL) {
1520					[copy release];
1521					PyObjCErr_ToObjCWithGILState(
1522							&state);
1523					return;
1524				}
1525			} else {
1526				Py_INCREF(*p);
1527			}
1528		}
1529
1530		free(ivarList);
1531		cls = class_getSuperclass(cls);
1532	}
1533
1534	PyGILState_Release(state);
1535	*(id*)resp = copy;
1536}
1537
1538/* -respondsToSelector: */
1539static void
1540object_method_respondsToSelector(
1541		ffi_cif* cif __attribute__((__unused__)),
1542		void* retval,
1543		void** args,
1544		void* userdata)
1545{
1546	id self = *(id*)args[0];
1547	SEL _meth = *(SEL*)args[1];
1548	SEL aSelector = *(SEL*)args[2];
1549	int* pres = (int*)retval; // Actually BOOL.
1550
1551	struct objc_super spr;
1552	PyObject* pyself;
1553	PyObject* pymeth;
1554
1555	PyObjC_BEGIN_WITH_GIL
1556		/* First check if we respond */
1557		pyself = PyObjCObject_New(self, PyObjCObject_kDEFAULT, YES);
1558		if (pyself == NULL) {
1559			*pres = NO;
1560			PyObjC_GIL_RETURNVOID;
1561		}
1562		pymeth = PyObjCObject_FindSelector(pyself, aSelector);
1563		Py_DECREF(pyself);
1564		if (pymeth) {
1565			*pres = YES;
1566
1567			if (PyObjCSelector_Check(pymeth) && (((PyObjCSelector*)pymeth)->sel_flags & PyObjCSelector_kCLASS_METHOD)) {
1568				*pres = NO;
1569			}
1570
1571			Py_DECREF(pymeth);
1572			PyObjC_GIL_RETURNVOID;
1573		}
1574		PyErr_Clear();
1575
1576	PyObjC_END_WITH_GIL
1577
1578	/* Check superclass */
1579	objc_superSetClass(spr, (Class)userdata);
1580	objc_superSetReceiver(spr, self);
1581
1582	*pres = ((int(*)(struct objc_super*, SEL, SEL))objc_msgSendSuper)(&spr, _meth, aSelector);
1583	return;
1584}
1585
1586/* -methodSignatureForSelector */
1587static void
1588object_method_methodSignatureForSelector(
1589		ffi_cif* cif __attribute__((__unused__)),
1590		void* retval,
1591		void** args,
1592		void* userdata)
1593{
1594	id self = *(id*)args[0];
1595	SEL _meth = *(SEL*)args[1];
1596	SEL aSelector = *(SEL*)args[2];
1597
1598	struct objc_super  spr;
1599	PyObject*          pyself;
1600	PyObject*          pymeth;
1601	NSMethodSignature** presult = (NSMethodSignature**)retval;
1602
1603	*presult = nil;
1604
1605	objc_superSetClass(spr, (Class)userdata);
1606	objc_superSetReceiver(spr, self);
1607
1608	NS_DURING
1609		*presult = objc_msgSendSuper(&spr, _meth, aSelector);
1610	NS_HANDLER
1611		*presult = nil;
1612	NS_ENDHANDLER
1613
1614	if (*presult != nil) {
1615		return;
1616	}
1617
1618	PyObjC_BEGIN_WITH_GIL
1619		pyself = PyObjCObject_New(self, PyObjCObject_kDEFAULT, YES);
1620		if (pyself == NULL) {
1621			PyErr_Clear();
1622			PyObjC_GIL_RETURNVOID;
1623		}
1624
1625		pymeth = PyObjCObject_FindSelector(pyself, aSelector);
1626		if (!pymeth) {
1627			Py_DECREF(pyself);
1628			PyErr_Clear();
1629			PyObjC_GIL_RETURNVOID;
1630		}
1631
1632	PyObjC_END_WITH_GIL
1633
1634	NS_DURING
1635		*presult =  [NSMethodSignature signatureWithObjCTypes:(
1636				(PyObjCSelector*)pymeth)->sel_python_signature];
1637	NS_HANDLER
1638		PyObjC_BEGIN_WITH_GIL
1639			Py_DECREF(pymeth);
1640			Py_DECREF(pyself);
1641
1642		PyObjC_END_WITH_GIL
1643		[localException raise];
1644	NS_ENDHANDLER
1645
1646	PyObjC_BEGIN_WITH_GIL
1647		Py_DECREF(pymeth);
1648		Py_DECREF(pyself);
1649
1650	PyObjC_END_WITH_GIL
1651
1652}
1653
1654/* -forwardInvocation: */
1655static void
1656object_method_forwardInvocation(
1657		ffi_cif* cif __attribute__((__unused__)),
1658		void* retval __attribute__((__unused__)),
1659		void** args,
1660		void* userdata)
1661{
1662	id self = *(id*)args[0];
1663	SEL _meth = *(SEL*)args[1];
1664	NSInvocation* invocation = *(NSInvocation**)args[2];
1665	SEL theSelector;
1666
1667	PyObject*	arglist;
1668	PyObject* 	result;
1669	PyObject*       v;
1670	BOOL		isAlloc;
1671	BOOL		isCFAlloc;
1672	Py_ssize_t      i;
1673	Py_ssize_t	len;
1674	PyObjCMethodSignature* signature;
1675	/*char		   argbuf[1024]; */
1676	const char* 		type;
1677	void* argbuf = NULL;
1678	int  err;
1679	Py_ssize_t   arglen;
1680	PyObject* pymeth;
1681	PyObject* pyself;
1682	volatile int have_output = 0;
1683	PyGILState_STATE state = PyGILState_Ensure();
1684
1685	pyself = PyObjCObject_New(self, PyObjCObject_kDEFAULT, YES);
1686	if (pyself == NULL) {
1687		PyObjCErr_ToObjCWithGILState(&state);
1688		return;
1689	}
1690
1691
1692	PyObjC_DURING
1693		theSelector = [invocation selector];
1694	PyObjC_HANDLER
1695		PyGILState_Release(state);
1696		[localException raise];
1697
1698		/* Avoid compiler warnings */
1699		theSelector = @selector(init);
1700
1701	PyObjC_ENDHANDLER
1702
1703	pymeth = PyObjCObject_FindSelector(pyself, theSelector);
1704
1705	if ((pymeth == NULL) || PyObjCNativeSelector_Check(pymeth)) {
1706		struct objc_super spr;
1707
1708		if (pymeth == NULL) {
1709			PyErr_Clear();
1710		}
1711
1712		Py_XDECREF(pymeth);
1713		Py_XDECREF(pyself);
1714
1715		objc_superSetClass(spr, (Class)userdata);
1716		objc_superSetReceiver(spr, self);
1717		PyGILState_Release(state);
1718		objc_msgSendSuper(&spr, _meth, invocation);
1719		return;
1720	}
1721
1722
1723	signature = PyObjCMethodSignature_FromSignature(
1724		PyObjCSelector_Signature(pymeth));
1725	len = signature->ob_size;
1726
1727	Py_XDECREF(pymeth); pymeth = NULL;
1728
1729	arglist = PyList_New(1);
1730	if (arglist == NULL) {
1731		Py_DECREF(signature);
1732		PyObjCErr_ToObjCWithGILState(&state);
1733		return;
1734	}
1735
1736	PyList_SET_ITEM(arglist, 0, pyself);
1737	pyself = NULL;
1738
1739	for (i = 2; i < len; i++) {
1740		type = signature->argtype[i].type;
1741		if (type == NULL) {
1742			PyErr_SetString(PyObjCExc_InternalError, "corrupt metadata");
1743			Py_DECREF(arglist);
1744			Py_DECREF(signature);
1745			PyObjCErr_ToObjCWithGILState(&state);
1746			return;
1747		}
1748
1749		arglen = PyObjCRT_SizeOfType(type);
1750
1751		if (arglen == -1) {
1752			Py_DECREF(arglist);
1753			Py_DECREF(signature);
1754			PyObjCErr_ToObjCWithGILState(&state);
1755			return;
1756		}
1757
1758		argbuf = PyMem_Malloc(arglen+64);
1759
1760		[invocation getArgument:argbuf atIndex:i];
1761
1762		/* XXX: this needs a lot of work to adapt to the new metadata!!! */
1763
1764		switch (*type) {
1765		case _C_INOUT:
1766			if (type[1] == _C_PTR) {
1767				have_output ++;
1768			}
1769			/* FALL THROUGH */
1770		case _C_IN: case _C_CONST:
1771			if (type[1] == _C_PTR) {
1772				v = pythonify_c_value(type+2, *(void**)argbuf);
1773			} else {
1774				v = pythonify_c_value(type+1, argbuf);
1775			}
1776			break;
1777		case _C_OUT:
1778			if (type[1] == _C_PTR) {
1779				have_output ++;
1780			}
1781			PyMem_Free(argbuf); argbuf = NULL;
1782			continue;
1783		default:
1784			v = pythonify_c_value(type, argbuf);
1785		}
1786		PyMem_Free(argbuf); argbuf = NULL;
1787
1788		if (v == NULL) {
1789			Py_DECREF(arglist);
1790			Py_DECREF(signature);
1791			PyObjCErr_ToObjCWithGILState(&state);
1792			return;
1793		}
1794
1795		if (PyList_Append(arglist, v) < 0) {
1796			Py_DECREF(arglist);
1797			Py_DECREF(signature);
1798			PyObjCErr_ToObjCWithGILState(&state);
1799			return;
1800		}
1801	}
1802
1803	v = PyList_AsTuple(arglist);
1804	if (v == NULL) {
1805		Py_DECREF(arglist);
1806		Py_DECREF(signature);
1807		PyObjCErr_ToObjCWithGILState(&state);
1808		return;
1809	}
1810	Py_DECREF(arglist);
1811	arglist = v; v = NULL;
1812
1813	result = PyObjC_CallPython(self, theSelector, arglist, &isAlloc, &isCFAlloc);
1814	Py_DECREF(arglist);
1815	if (result == NULL) {
1816		Py_DECREF(signature);
1817		PyObjCErr_ToObjCWithGILState(&state);
1818		return;
1819	}
1820
1821	type = signature->rettype.type;
1822	arglen = PyObjCRT_SizeOfType(type);
1823
1824	if (arglen == -1) {
1825		Py_DECREF(signature);
1826		PyObjCErr_ToObjCWithGILState(&state);
1827		return;
1828	}
1829
1830	if (!have_output) {
1831		if (*type  != _C_VOID && *type != _C_ONEWAY) {
1832			argbuf = PyMem_Malloc(arglen+64);
1833
1834			err = depythonify_c_value(type, result, argbuf);
1835			if (err == -1) {
1836				PyMem_Free(argbuf);
1837				Py_DECREF(signature);
1838				PyObjCErr_ToObjCWithGILState(&state);
1839				return;
1840			}
1841			if (isAlloc) {
1842				[(*(id*)argbuf) retain];
1843			} else if (isCFAlloc) {
1844				if (*(id*)argbuf != nil) {
1845					CFRetain((*(id*)argbuf));
1846				}
1847			}
1848			[invocation setReturnValue:argbuf];
1849			PyMem_Free(argbuf);
1850		}
1851		Py_DECREF(result);
1852
1853	} else {
1854		Py_ssize_t idx;
1855		PyObject* real_res;
1856
1857		if (*type == _C_VOID && have_output == 1) {
1858			/* One output argument, and a 'void' return value,
1859			 * the python method returned just the output
1860			 * argument
1861			 */
1862			/* This should be cleaned up, unnecessary code
1863			 * duplication
1864			 */
1865
1866			for (i = 2; i < len;i++) {
1867				void* ptr;
1868				type = signature->argtype[i].type;
1869
1870				if (arglen == -1) {
1871					Py_DECREF(signature);
1872					PyObjCErr_ToObjCWithGILState(&state);
1873					return;
1874				}
1875
1876				switch (*type) {
1877				case _C_INOUT: case _C_OUT:
1878					if (type[1] != _C_PTR) {
1879						continue;
1880					}
1881					type += 2;
1882					break;
1883				default:
1884					continue;
1885				}
1886
1887				[invocation getArgument:&ptr atIndex:i];
1888				err = depythonify_c_value(type, result, ptr);
1889				if (err == -1) {
1890					Py_DECREF(signature);
1891					PyObjCErr_ToObjCWithGILState(&state);
1892					return;
1893				}
1894				if (result->ob_refcnt == 1 && type[0] == _C_ID) {
1895					/* make sure return value doesn't die before
1896					 * the caller can get its hands on it.
1897					 */
1898					[[*(id*)ptr retain] autorelease];
1899				}
1900
1901				/* We have exactly 1 output argument */
1902				break;
1903
1904			}
1905
1906			Py_DECREF(signature);
1907			Py_DECREF(result);
1908			PyGILState_Release(state);
1909			return;
1910		}
1911
1912		if (*type != _C_VOID) {
1913			if (!PyTuple_Check(result)
1914			     || PyTuple_Size(result) != have_output+1) {
1915				PyErr_Format(PyExc_TypeError,
1916					"%s: Need tuple of %d arguments as result",
1917					sel_getName(theSelector),
1918					have_output+1);
1919				Py_DECREF(result);
1920				Py_DECREF(signature);
1921				PyObjCErr_ToObjCWithGILState(&state);
1922				return;
1923			}
1924			idx = 1;
1925			real_res = PyTuple_GET_ITEM(result, 0);
1926
1927			argbuf = PyMem_Malloc(arglen+64);
1928
1929			err = depythonify_c_value(type, real_res, argbuf);
1930			if (err == -1) {
1931				Py_DECREF(signature);
1932				PyObjCErr_ToObjCWithGILState(&state);
1933				PyMem_Free(argbuf);
1934				return;
1935			}
1936			if (isAlloc) {
1937				[(*(id*)argbuf) retain];
1938			} else if (isCFAlloc) {
1939				CFRetain(*(id*)argbuf);
1940			}
1941			[invocation setReturnValue:argbuf];
1942			PyMem_Free(argbuf);
1943
1944		} else {
1945			if (!PyTuple_Check(result)
1946			     || PyTuple_Size(result) != have_output) {
1947				PyErr_Format(PyExc_TypeError,
1948					"%s: Need tuple of %d arguments as result",
1949					sel_getName(theSelector),
1950					have_output);
1951				Py_DECREF(signature);
1952				Py_DECREF(result);
1953				PyObjCErr_ToObjCWithGILState(&state);
1954				return;
1955			}
1956			idx = 0;
1957		}
1958
1959
1960		for (i = 2; i < len;i++) {
1961			void* ptr;
1962			type = signature->argtype[i].type;
1963
1964			if (arglen == -1) {
1965				Py_DECREF(signature);
1966				PyObjCErr_ToObjCWithGILState(&state);
1967				return;
1968			}
1969
1970			switch (*type) {
1971			case _C_INOUT: case _C_OUT:
1972				if (type[1] != _C_PTR) {
1973					continue;
1974				}
1975				type += 2;
1976				break;
1977			default:
1978				continue;
1979			}
1980
1981			[invocation getArgument:&ptr atIndex:i];
1982			v = PyTuple_GET_ITEM(result, idx++);
1983			err = depythonify_c_value(type, v, ptr);
1984			if (err == -1) {
1985				Py_DECREF(signature);
1986				PyObjCErr_ToObjCWithGILState(&state);
1987				return;
1988			}
1989			if (v->ob_refcnt == 1 && type[0] == _C_ID) {
1990				/* make sure return value doesn't die before
1991				 * the caller can get its hands on it.
1992			   	 */
1993				[[*(id*)ptr retain] autorelease];
1994			}
1995
1996		}
1997		Py_DECREF(result);
1998	}
1999	Py_DECREF(signature);
2000	PyGILState_Release(state);
2001}
2002
2003/*
2004 * XXX: Function PyObjC_CallPython should be moved
2005 */
2006PyObject*
2007PyObjC_CallPython(id self, SEL selector, PyObject* arglist, BOOL* isAlloc, BOOL* isCFAlloc)
2008{
2009	PyObject* pyself = NULL;
2010	PyObject* pymeth = NULL;
2011	PyObject* result;
2012
2013	pyself = pythonify_c_value(@encode(id), &self);
2014	if (pyself == NULL) {
2015		return NULL;
2016	}
2017
2018	if (PyObjCClass_Check(pyself)) {
2019		pymeth = PyObjCClass_FindSelector(pyself, selector, YES);
2020	} else {
2021		pymeth = PyObjCObject_FindSelector(pyself, selector);
2022	}
2023	if (pymeth == NULL) {
2024		Py_DECREF(pyself);
2025		return NULL;
2026	}
2027
2028	if (NULL != ((PyObjCSelector*)pymeth)->sel_self) {
2029		/* The selector is a bound selector, we didn't expect that...*/
2030		PyObject* arg_self;
2031
2032		arg_self = PyTuple_GET_ITEM(arglist, 0);
2033		if (arg_self == NULL) {
2034			return NULL;
2035		}
2036		if (arg_self != ((PyObjCSelector*)pymeth)->sel_self) {
2037
2038			PyErr_SetString(PyExc_TypeError,
2039				"PyObjC_CallPython called with 'self' and "
2040				"a method bound to another object");
2041			return NULL;
2042		}
2043
2044		arglist = PyTuple_GetSlice(arglist, 1, PyTuple_Size(arglist));
2045		if (arglist == NULL) {
2046			return NULL;
2047		}
2048	} else {
2049		Py_INCREF(arglist);
2050	}
2051
2052	if (isAlloc != NULL) {
2053		*isAlloc = PyObjCSelector_GetMetadata(pymeth)->rettype.alreadyRetained;
2054	}
2055	if (isCFAlloc != NULL) {
2056		*isCFAlloc = PyObjCSelector_GetMetadata(pymeth)->rettype.alreadyCFRetained;
2057	}
2058
2059	result = PyObject_Call(pymeth, arglist, NULL);
2060	Py_DECREF(arglist);
2061	Py_DECREF(pymeth);
2062	Py_DECREF(pyself);
2063
2064	if (result == NULL) {
2065		return NULL;
2066	}
2067
2068	return result;
2069}
2070
2071static void
2072object_method_valueForKey_(
2073		ffi_cif* cif __attribute__((__unused__)),
2074		void* retval,
2075		void** args,
2076		void* userdata)
2077{
2078	// This method does the following:
2079	//     - Checks super implementation
2080	//     - if [[self class] accessInstanceVariablesDirectly]
2081	//         - Checks for attribute key
2082	//         - Checks for attribute _key
2083	int r;
2084	id self = *(id*)args[0];
2085	SEL _meth = *(SEL*)args[1];
2086	NSString* key = *(NSString**)args[2];
2087
2088	struct objc_super spr;
2089
2090	// First check super
2091	NS_DURING
2092		objc_superSetClass(spr, (Class)userdata);
2093		objc_superSetReceiver(spr, self);
2094		*((id *)retval) = (id)objc_msgSendSuper(&spr, _meth, key);
2095	NS_HANDLER
2096		/* Parent doesn't know the key, try to create in the
2097		 * python side, just like for plain python objects.
2098		 */
2099		if (([[localException name] isEqual:@"NSUnknownKeyException"]
2100			) && [[self class] accessInstanceVariablesDirectly]) {
2101
2102			PyGILState_STATE state = PyGILState_Ensure();
2103			PyObject* selfObj = PyObjCObject_New(self, PyObjCObject_kDEFAULT, YES);
2104			PyObject *res = NULL;
2105			r = -1;
2106			do {
2107				res = PyObject_GetAttrString(selfObj, (char *)[key UTF8String]);
2108				if (res == NULL) {
2109					PyErr_Clear();
2110					res = PyObject_GetAttrString(selfObj, (char *)[[@"_" stringByAppendingString:key] UTF8String]);
2111					if (res == NULL) {
2112						break;
2113					}
2114				}
2115
2116				/* Check that we don't accidently return
2117				 * an accessor method.
2118				 */
2119				if (PyObjCSelector_Check(res) &&
2120					((PyObjCSelector*)res)->sel_self == selfObj) {
2121					Py_DECREF(res); res = NULL;
2122					break;
2123				}
2124				r = depythonify_c_value(@encode(id), res, retval);
2125			} while (0);
2126			Py_DECREF(selfObj);
2127			Py_XDECREF(res);
2128			if (r == -1) {
2129				PyErr_Clear();
2130				PyGILState_Release(state);
2131				[localException raise];
2132			}
2133			PyGILState_Release(state);
2134		} else {
2135			[localException raise];
2136		}
2137	NS_ENDHANDLER
2138
2139}
2140
2141
2142#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
2143
2144static void
2145object_method_willOrDidChangeValueForKey_(
2146		ffi_cif* cif __attribute__((__unused__)),
2147		void* retval __attribute__((__unused__)),
2148		void** args,
2149		void* userdata) {
2150	struct objc_super spr;
2151	id self = *(id*)args[0];
2152	SEL _meth = *(SEL*)args[1];
2153	NSString* key = *(NSString**)args[2];
2154
2155#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
2156	BOOL isSet = (_meth == @selector(willChangeValueForKey:));
2157	if (_UseKVO(self, key, isSet)) {
2158		objc_superSetClass(spr, (Class)userdata);
2159		objc_superSetReceiver(spr, self);
2160		(void)objc_msgSendSuper(&spr, _meth, key);
2161	}
2162
2163#else
2164	objc_superSetClass(spr, (Class)userdata);
2165	objc_superSetReceiver(spr, self);
2166	(void)objc_msgSendSuper(&spr, _meth, key);
2167#endif
2168
2169}
2170
2171#endif
2172
2173static void
2174object_method_setValue_forKey_(
2175		ffi_cif* cif __attribute__((__unused__)),
2176		void* retval __attribute__((__unused__)),
2177		void** args,
2178		void* userdata)
2179{
2180	// This method does the following:
2181	//     - Checks super implementation
2182	//     - if [[self class] accessInstanceVariablesDirectly]
2183	//	       - Checks for attribute _key and sets if present
2184	//		   - Sets attribute key
2185	int r;
2186	struct objc_super spr;
2187	id self = *(id*)args[0];
2188	SEL _meth = *(SEL*)args[1];
2189	id value = *(id*)args[2];
2190	NSString* key = *(NSString**)args[3];
2191
2192#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
2193	// Set up a KVO stack so you only get one notification from this
2194	NS_DURING
2195		if (_KVOHackLevel() == BROKEN_KVO) {
2196			[self willChangeValueForKey:key];
2197		}
2198	NS_HANDLER
2199	NS_ENDHANDLER
2200#endif
2201
2202	NS_DURING
2203		// First check super
2204		objc_superSetClass(spr, (Class)userdata);
2205		objc_superSetReceiver(spr, self);
2206		(void)objc_msgSendSuper(&spr, _meth, value, key);
2207	NS_HANDLER
2208		/* Parent doesn't know the key, try to create in the
2209		 * python side, just like for plain python objects.
2210		 */
2211		if (([[localException name] isEqual:@"NSUnknownKeyException"]
2212			) && [[self class] accessInstanceVariablesDirectly]) {
2213
2214			PyGILState_STATE state = PyGILState_Ensure();
2215			PyObject* val = pythonify_c_value(@encode(id), &value);
2216			if (val == NULL) {
2217				PyErr_Clear();
2218				PyGILState_Release(state);
2219
2220#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
2221				// Pop the KVO stack
2222				if (_KVOHackLevel() == BROKEN_KVO) {
2223				    [self didChangeValueForKey:key];
2224				}
2225#endif
2226
2227				[localException raise];
2228			}
2229			PyObject* res = NULL;
2230			PyObject* selfObj = PyObjCObject_New(self, PyObjCObject_kDEFAULT, YES);
2231			r = -1;
2232			do {
2233				char *rawkey = (char *)[[@"_" stringByAppendingString:key] UTF8String];
2234				res = PyObject_GetAttrString(selfObj, rawkey);
2235				if (res != NULL) {
2236					r = PyObject_SetAttrString(selfObj, rawkey, val);
2237					if (r != -1) {
2238						break;
2239					}
2240				}
2241				PyErr_Clear();
2242				rawkey = (char *)[key UTF8String];
2243				r = PyObject_SetAttrString(selfObj, rawkey, val);
2244			} while (0);
2245			Py_DECREF(selfObj);
2246			Py_DECREF(val);
2247			Py_XDECREF(res);
2248			if (r == -1) {
2249				PyErr_Clear();
2250				PyGILState_Release(state);
2251#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
2252				// Pop the KVO stack
2253				if (_KVOHackLevel() == BROKEN_KVO) {
2254				    [self didChangeValueForKey:key];
2255				}
2256#endif
2257				[localException raise];
2258			}
2259			PyGILState_Release(state);
2260		} else {
2261#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
2262			// Pop the KVO stack
2263			if (_KVOHackLevel() == BROKEN_KVO) {
2264				[self didChangeValueForKey:key];
2265			}
2266#endif
2267			[localException raise];
2268		}
2269	NS_ENDHANDLER
2270
2271#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_4
2272	// Pop the KVO stack
2273	if (_KVOHackLevel() == BROKEN_KVO) {
2274		[self didChangeValueForKey:key];
2275	}
2276#endif
2277}
2278