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