1/* 2 * Implementation of objective-C object wrapper 3 * 4 * NOTE: We're using CFRetain and CFRelease to manage the retaincount of the Objective-C 5 * objects because that will do the right thing when Garbage Collection is involved. 6 */ 7#include "pyobjc.h" 8 9#include <stddef.h> 10 11#include <objc/Object.h> 12 13/* 14 * Support for NSKeyValueObserving on MacOS X 10.3 and later. 15 * 16 */ 17 18/* 19 * XXX: for reasons beyond my current comprehension the "legacy" block must be active, otherwise we 20 * get a fatal python error. 21 */ 22#if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3 23 24/* Deal with platforms that don't support KVO */ 25 26static int 27_KVOHackLevel(void) { 28 static int _checkedKVO = 0; 29 if (_checkedKVO == 0) { 30 if ([NSObject instancesRespondToSelector:@selector(willChangeValueForKey:)] && 31 [NSObject instancesRespondToSelector:@selector(didChangeValueForKey:)]) { 32 _checkedKVO = 1; 33 34 } else { 35 36 _checkedKVO = -1; 37 } 38 } 39 return _checkedKVO; 40} 41 42static void 43_UseKVO(NSObject *self, NSString *key, BOOL willChange) 44{ 45 PyObjC_DURING 46 int _checkedKVO = _KVOHackLevel(); 47 if (_checkedKVO == -1 || [key characterAtIndex:0] == (unichar)'_') { 48 /* pass */ 49 } else if (willChange) { 50 [self willChangeValueForKey:key]; 51 } else { 52 [self didChangeValueForKey:key]; 53 } 54 PyObjC_HANDLER 55 PyObjC_ENDHANDLER 56} 57 58#else 59 60static void 61_UseKVO(NSObject *self, NSString *key, BOOL willChange) 62{ 63 PyObjC_DURING 64 if ([key characterAtIndex:0] == (unichar)'_') { 65 /* pass */ 66 } else if (willChange) { 67 [self willChangeValueForKey:key]; 68 } else { 69 [self didChangeValueForKey:key]; 70 } 71 PyObjC_HANDLER 72 PyObjC_ENDHANDLER 73} 74 75#endif 76 77static PyObject* 78object_new( 79 PyTypeObject* type __attribute__((__unused__)), 80 PyObject* args, 81 PyObject* kwds) 82{ 83static char* keywords[] = { "cobject", "c_void_p", NULL }; 84 PyObject* cobject = NULL; 85 PyObject* c_void_p = NULL; 86 87 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", keywords, &cobject, &c_void_p)) { 88 return NULL; 89 } 90 91 if (cobject != NULL && c_void_p != NULL) { 92 PyErr_SetString(PyExc_TypeError, 93 "Pass either cobject or c_void_p, but not both"); 94 return NULL; 95 } 96 97 if (cobject != NULL && PyCapsule_CheckExact(cobject)) { 98 NSObject* p = PyCapsule_GetPointer(cobject, "objc.__object__"); 99 if (PyErr_Occurred()) { 100 return NULL; 101 } 102 103 return PyObjC_IdToPython(p); 104 105 } else if (c_void_p != NULL) { 106 NSObject* p; 107 PyObject* attrval; 108 109 if (PyLong_Check(c_void_p) 110#if PY_MAJOR_VERSION == 2 111 || PyInt_Check(c_void_p) 112#endif 113 ) { 114 attrval = c_void_p; 115 Py_INCREF(attrval); 116 } else { 117 attrval = PyObject_GetAttrString(c_void_p, "value"); 118 if (attrval == NULL) { 119 return NULL; 120 } 121 } 122 123 if ( 124#if PY_MAJOR_VERSION == 2 125 PyInt_Check(attrval) || 126 /* NOTE: PyLong_AsVoidPtr works on Int objects as well */ 127#endif /* PY_MAJOR_VERSION == 2 */ 128 PyLong_Check(attrval) 129 ) { 130 p = PyLong_AsVoidPtr(attrval); 131 if (p == NULL && PyErr_Occurred()) { 132 Py_DECREF(attrval); 133 return NULL; 134 } 135 136 } else { 137 PyErr_SetString(PyExc_ValueError, 138 "c_void_p.value is not an integer"); 139 return NULL; 140 } 141 Py_DECREF(attrval); 142 return PyObjC_IdToPython(p); 143 144 } else { 145 PyErr_SetString(PyExc_TypeError, 146 "Use class methods to instantiate new Objective-C objects"); 147 return NULL; 148 } 149} 150 151static PyObject* 152object_repr(PyObject* _self) 153{ 154 PyObjCObject* self = (PyObjCObject*)_self; 155 PyObject* res; 156 157 if (self->flags & PyObjCObject_kMAGIC_COOKIE) { 158 return PyText_FromFormat( 159 "<%s objective-c magic instance %p>", 160 Py_TYPE(self)->tp_name, self->objc_object); 161 } 162 163 if ((self->flags & PyObjCObject_kUNINITIALIZED) == 0 && !PyObjCObject_IsClassic(self)) { 164 /* Try to call the method 'description', which is the ObjC 165 * equivalent of __repr__. If that fails we'll fall back to 166 * the default repr. 167 * Don't call 'description' for uninitialized objects, that 168 * is undefined behaviour and will crash the interpreter sometimes. 169 */ 170 res = PyObject_CallMethod((PyObject*)self, "description", NULL); 171 //res = NULL; 172 if (res == NULL) { 173 PyErr_Clear(); 174 } else { 175 return res; 176 } 177 } 178 return PyText_FromFormat( 179 "<%s objective-c instance %p>", 180 Py_TYPE(self)->tp_name, self->objc_object); 181} 182 183static void 184object_del(PyObject* obj __attribute__((__unused__))) 185{ 186 /* Dummy function, we do not want the default implementation */ 187} 188 189 190static void 191object_dealloc(PyObject* obj) 192{ 193 /* 194 * Save exception information, needed because releasing the object 195 * might clear or modify the exception state. 196 */ 197 PyObject* ptype, *pvalue, *ptraceback; 198 PyErr_Fetch(&ptype, &pvalue, &ptraceback); 199 200 if (PyObjCObject_IsBlock(obj)) { 201 PyObjCMethodSignature* v = PyObjCObject_GetBlock(obj); 202 PyObjCObject_SET_BLOCK(obj, NULL); 203 Py_XDECREF(v); 204 } 205 206 207 if (PyObjCObject_GetFlags(obj) != PyObjCObject_kDEALLOC_HELPER 208 && PyObjCObject_GetObject(obj) != nil) { 209 /* Release the proxied object, we don't have to do this when 210 * there is no proxied object. 211 */ 212 PyObjC_UnregisterPythonProxy( 213 PyObjCObject_GetObject(obj), obj); 214 215 if (PyObjCObject_IsClassic(obj)) { 216 /* pass */ 217 218 } else if ((((PyObjCObject*)obj)->flags 219 & PyObjCObject_kSHOULD_NOT_RELEASE)) { 220 /* pass */ 221 222 } else if (((PyObjCObject*)obj)->flags 223 & PyObjCObject_kUNINITIALIZED) { 224 /* Freeing of an uninitialized object, just leak because 225 * there is no reliable manner to free such objects. 226 * 227 * - [obj release] doesn't work because some classes 228 * cause crashes for uninitialized objects 229 * - [[obj init] release] also doesn't work because 230 * not all classes implement -init 231 * - [obj dealloc] doesn't work for class 232 * clusters like NSArray. 233 */ 234 char buf[256]; 235 snprintf(buf, sizeof(buf), 236 "leaking an uninitialized object of type %s", 237 Py_TYPE(obj)->tp_name); 238 PyErr_Warn(PyObjCExc_UnInitDeallocWarning, buf); 239 ((PyObjCObject*)obj)->objc_object = nil; 240 241 } else { 242 PyObjC_DURING 243 if (((PyObjCObject*)obj)->flags & PyObjCObject_kCFOBJECT) { 244 CFRelease(((PyObjCObject*)obj)->objc_object); 245 } else if (strcmp(object_getClassName(((PyObjCObject*)obj)->objc_object), 246 "NSAutoreleasePool") != 0) { 247 248 CFRelease(((PyObjCObject*)obj)->objc_object); 249 } else { 250 CFRelease(((PyObjCObject*)obj)->objc_object); 251 } 252 253 PyObjC_HANDLER 254 NSLog(@"PyObjC: Exception during dealloc of proxy: %@", 255 localException); 256 257 PyObjC_ENDHANDLER 258 ((PyObjCObject*)obj)->objc_object = nil; 259 } 260 } 261 262 Py_TYPE(obj)->tp_free(obj); 263 264 PyErr_Restore(ptype, pvalue, ptraceback); 265} 266 267 268static inline PyObject* 269_type_lookup(PyTypeObject* tp, PyObject* name) 270{ 271 Py_ssize_t i, n; 272 PyObject *mro, *base, *dict; 273 PyObject *descr = NULL; 274 PyObject* protDict; 275 PyObject* res; 276 277 /* FIXME: Support for method name cache */ 278 279 /* Look in tp_dict of types in MRO */ 280 mro = tp->tp_mro; 281 if (mro == NULL) { 282 return NULL; 283 } 284 res = NULL; 285 assert(PyTuple_Check(mro)); 286 n = PyTuple_GET_SIZE(mro); 287 for (i = 0; i < n; i++) { 288 base = PyTuple_GET_ITEM(mro, i); 289 290 if (PyObjCClass_Check(base)) { 291 PyObjCClass_CheckMethodList(base, 0); 292 protDict = ((PyObjCClassObject*)base)->protectedMethods; 293 dict = ((PyTypeObject *)base)->tp_dict; 294 295 } else if (PyType_Check(base)) { 296 protDict = NULL; 297 dict = ((PyTypeObject *)base)->tp_dict; 298 299 300#if PY_MAJOR_VERSION == 2 301 } else if (PyClass_Check(base)) { 302 dict = ((PyClassObject*)base)->cl_dict; 303 protDict = NULL; 304#endif 305 } else { 306 return NULL; 307 } 308 assert(dict && PyDict_Check(dict)); 309 descr = PyDict_GetItem(dict, name); 310 if (descr != NULL) { 311 break; 312 } 313 314 if (protDict) { 315 descr = PyDict_GetItem(protDict, name); 316 if (descr != NULL) { 317 break; 318 } 319 } 320 } 321 322 return descr; 323} 324 325static PyObject** _get_dictptr(PyObject* obj) 326{ 327 Py_ssize_t dictoffset; 328 id obj_object; 329 dictoffset = PyObjCClass_DictOffset((PyObject*)Py_TYPE(obj)); 330 if (dictoffset == 0) return NULL; 331 obj_object = PyObjCObject_GetObject(obj); 332 assert(obj_object != nil); 333 return (PyObject**)(((char*)obj_object) + dictoffset); 334} 335 336 337static PyObject * 338object_getattro(PyObject *obj, PyObject * volatile name) 339{ 340 PyTypeObject *tp = NULL; 341 PyObject *descr = NULL; 342 PyObject *res = NULL; 343 descrgetfunc f; 344 PyObject** dictptr; 345 char* namestr; 346 id obj_inst; 347 PyObject* bytes; 348 349 if (name == NULL) { 350 PyErr_SetString(PyExc_TypeError, "<nil> name"); 351 return NULL; 352 } 353 354 if (PyUnicode_Check(name)) { 355 bytes = PyUnicode_AsEncodedString(name, NULL, NULL); 356 if (bytes == NULL) return NULL; 357#if PY_MAJOR_VERSION == 2 358 } else if (PyString_Check(name)) { 359 bytes = name; Py_INCREF(bytes); 360#endif 361 } else { 362 PyErr_Format(PyExc_TypeError, 363 "attribute name must be string, got %s", 364 Py_TYPE(name)->tp_name); 365 return NULL; 366 } 367 368 369 370 namestr = PyBytes_AsString(bytes); 371 if (namestr == NULL) { 372 if (!PyErr_Occurred()) { 373 PyErr_SetString(PyExc_ValueError, "Empty name"); 374 } 375 return NULL; 376 } 377 378 obj_inst = PyObjCObject_GetObject(obj); 379 if (!obj_inst) { 380#if PY_MAJOR_VERSION == 2 381 PyErr_Format(PyExc_AttributeError, 382 "cannot access attribute '%.400s' of NIL '%.50s' object", 383 PyString_AS_STRING(name), 384 Py_TYPE(obj)->tp_name); 385#else 386 PyErr_Format(PyExc_AttributeError, 387 "cannot access attribute '%U' of NIL '%.50s' object", 388 name, 389 Py_TYPE(obj)->tp_name); 390#endif 391 goto done; 392 } 393 394 if (PyObjCObject_GetFlags(obj) & PyObjCObject_kMAGIC_COOKIE) { 395 /* A magic cookie object, don't treat this like a normal 396 * object because that might cause havoc. 397 */ 398 399 } else { 400 /* Special hack for KVO on MacOS X, when an object is observed it's 401 * ISA is changed by the runtime. We change the python type as well. 402 */ 403 tp = (PyTypeObject*)PyObjCClass_New(object_getClass(obj_inst)); 404 405 descr = NULL; 406 407 if (tp != Py_TYPE(obj)) { 408 /* Workaround for KVO implementation feature */ 409 PyObject* dict; 410 411 if (tp->tp_dict == NULL) { 412 if (PyType_Ready(tp) < 0) 413 goto done; 414 } 415 416// XXX: You'd expect the code below works, but it actually doesn't. Need to check why. 417// Py_DECREF(Py_TYPE(obj)); 418// Py_TYPE(obj) = tp; 419// 420 421 PyObjCClass_CheckMethodList((PyObject*)tp, 0); 422 dict = tp->tp_dict; 423 424 assert(dict && PyDict_Check(dict)); 425 descr = PyDict_GetItem(dict, name); 426 } 427 Py_DECREF(tp); tp = NULL; 428 } 429 430 tp = Py_TYPE(obj); 431 if (tp->tp_dict == NULL) { 432 if (PyType_Ready(tp) < 0) 433 goto done; 434 } 435 436 /* replace _PyType_Lookup */ 437 if (descr == NULL) { 438 descr = _type_lookup(tp, name); 439 } 440 441 f = NULL; 442 if (descr != NULL 443#if PY_MAJOR_VERSION == 2 444 && PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS) 445#endif 446 ) { 447 f = Py_TYPE(descr)->tp_descr_get; 448 if (f != NULL && PyDescr_IsData(descr)) { 449 res = f(descr, obj, (PyObject*)Py_TYPE(obj)); 450 goto done; 451 } 452 } 453 454 if (strcmp(PyBytes_AS_STRING(bytes), "__del__") == 0) { 455 res = PyObjCClass_GetDelMethod((PyObject*)Py_TYPE(obj)); 456 if (res != NULL) { 457 /* XXX: bind self */ 458 } 459 goto done; 460 } 461 462 /* First try the __dict__ */ 463 dictptr = _get_dictptr(obj); 464 465 if (dictptr != NULL) { 466 PyObject *dict; 467 468 if (strcmp(PyBytes_AS_STRING(bytes), "__dict__") == 0) { 469 res = *dictptr; 470 if (res == NULL) { 471 *dictptr = PyDict_New(); 472 if (*dictptr == NULL) { 473 PyErr_Clear(); 474 } 475 res = *dictptr; 476 } 477 if (res != NULL) { 478 Py_INCREF(res); 479 goto done; 480 } 481 } else { 482 dict = *dictptr; 483 if (dict != NULL) { 484 res = PyDict_GetItem(dict, name); 485 if (res != NULL) { 486 Py_INCREF(res); 487 goto done; 488 } 489 } 490 } 491 } 492 493 if (f != NULL) { 494 res = f(descr, obj, (PyObject*)Py_TYPE(obj)); 495 goto done; 496 } 497 498 if (descr != NULL) { 499 Py_INCREF(descr); 500 res = descr; 501 goto done; 502 } 503 504 if (!PyObjCObject_IsClassic(obj)) { 505 res = PyObjCSelector_FindNative(obj, namestr); 506 if (res) goto done; 507 } 508 509 PyErr_Format(PyExc_AttributeError, 510 "'%.50s' object has no attribute '%.400s'", 511 tp->tp_name, namestr); 512 513done: 514 if (res != NULL) { 515 /* class methods cannot be accessed through instances */ 516 if (PyObjCSelector_Check(res) 517 && PyObjCSelector_IsClassMethod(res)) { 518 Py_DECREF(res); 519#if PY_MAJOR_VERSION == 2 520 PyErr_Format(PyExc_AttributeError, 521 "'%.50s' object has no attribute '%.400s'", 522 tp->tp_name, PyString_AS_STRING(name)); 523#else 524 PyErr_Format(PyExc_AttributeError, 525 "'%.50s' object has no attribute '%U'", 526 tp->tp_name, name); 527#endif 528 res = NULL; 529 } 530 } 531 Py_DECREF(bytes); 532 return res; 533} 534 535 536static int 537object_setattro(PyObject *obj, PyObject *name, PyObject *value) 538{ 539 PyTypeObject *tp = Py_TYPE(obj); 540 PyObject *descr; 541 descrsetfunc f; 542 PyObject** dictptr; 543 int res; 544 id obj_inst; 545 NSString *obj_name; 546 PyObject* bytes; 547 548 if (PyUnicode_Check(name)) { 549 bytes = PyUnicode_AsEncodedString(name, NULL, NULL); 550 if (bytes == NULL) return -1; 551#if PY_MAJOR_VERSION == 2 552 } else if (PyString_Check(name)) { 553 bytes = name; Py_INCREF(bytes); 554#endif 555 } else { 556 PyErr_Format(PyExc_TypeError, 557 "attribute name must be string, got %s", 558 Py_TYPE(name)->tp_name); 559 return -1; 560 } 561 562 obj_inst = PyObjCObject_GetObject(obj); 563 if (obj_inst == nil) { 564 PyErr_Format(PyExc_AttributeError, 565 "Cannot set '%s.400s' on NIL '%.50s' object", 566 PyBytes_AS_STRING(bytes), 567 tp->tp_name); 568 Py_DECREF(bytes); 569 return -1; 570 } 571 572 obj_name = nil; 573 if (((PyObjCClassObject*)tp)->useKVO) { 574 if ((PyObjCObject_GetFlags(obj) & PyObjCObject_kUNINITIALIZED) == 0) { 575 obj_name = [NSString stringWithUTF8String:PyBytes_AS_STRING(bytes)]; 576 _UseKVO((NSObject *)obj_inst, obj_name, YES); 577 } 578 } 579 descr = _type_lookup(tp, name); 580 f = NULL; 581 if (descr != NULL 582#if PY_MAJOR_VERSION == 2 583 && PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_HAVE_CLASS) 584#endif 585 ) { 586 f = Py_TYPE(descr)->tp_descr_set; 587 if (f != NULL && PyDescr_IsData(descr)) { 588 res = f(descr, obj, value); 589 goto done; 590 } 591 } 592 593 dictptr = _get_dictptr(obj); 594 if (dictptr != NULL) { 595 PyObject *dict; 596 597 dict = *dictptr; 598 599 if (dict == NULL && value != NULL) { 600 dict = PyDict_New(); 601 if (dict == NULL) { 602 res = -1; 603 goto done; 604 } 605 606 *dictptr = dict; 607 } 608 if (dict != NULL) { 609 if (value == NULL) { 610 res = PyDict_DelItem(dict, name); 611 } else { 612 res = PyDict_SetItem(dict, name, value); 613 } 614 if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) { 615 PyErr_SetObject(PyExc_AttributeError, name); 616 } 617 goto done; 618 } 619 } 620 621 if (f != NULL) { 622 res = f(descr, obj, value); 623 goto done; 624 } 625 626 if (descr == NULL) { 627 PyErr_Format(PyExc_AttributeError, 628 "'%.50s' object has no attribute '%.400s'", 629 tp->tp_name, PyBytes_AS_STRING(bytes)); 630 res = -1; 631 goto done; 632 } 633 634 PyErr_Format(PyExc_AttributeError, 635 "'%.50s' object attribute '%.400s' is read-only", 636 tp->tp_name, PyBytes_AS_STRING(bytes)); 637 res = -1; 638 done: 639 if (obj_inst && obj_name) { 640 _UseKVO((NSObject *)obj_inst, obj_name, NO); 641 } 642 Py_DECREF(bytes); 643 return res; 644} 645 646PyDoc_STRVAR(objc_get_real_class_doc, "Return the current ISA of the object"); 647static PyObject* 648objc_get_real_class(PyObject* self, void* closure __attribute__((__unused__))) 649{ 650 id obj_object; 651 PyObject* ret; 652 653 obj_object = PyObjCObject_GetObject(self); 654 assert(obj_object != nil); 655 ret = PyObjCClass_New(object_getClass(obj_object)); 656 if (ret != (PyObject*)Py_TYPE(self)) { 657 Py_DECREF(Py_TYPE(self)); 658 Py_TYPE(self) = (PyTypeObject*)ret; 659 Py_INCREF(ret); 660 } 661 return ret; 662} 663 664PyDoc_STRVAR(obj_get_instanceMethods_doc, 665"The attributes of this field are the instance methods of this object. This\n" 666"can be used to force access to an instance method." 667); 668static PyObject* 669obj_get_instanceMethods(PyObject* _self, void* closure __attribute__((__unused__))) 670{ 671 PyObjCObject* self = (PyObjCObject*)_self; 672 return PyObjCMethodAccessor_New((PyObject*)self, 0); 673} 674 675static PyObject* 676obj_get_blocksignature(PyObject* self, void* closure __attribute__((__unused__))) 677{ 678 if (PyObjCObject_IsBlock(self)) { 679 PyObject* v = (PyObject*)PyObjCObject_GetBlock(self); 680 if (v != NULL) { 681 Py_INCREF(v); 682 return v; 683 } 684 } 685 Py_INCREF(Py_None); 686 return Py_None; 687} 688 689static int 690obj_set_blocksignature(PyObject* self, PyObject* newVal, void* closure __attribute__((__unused__))) 691{ 692 if (!PyObjCObject_IsBlock(self)) { 693 PyErr_SetString(PyExc_TypeError, "You can only change this value on blocks"); 694 return -1; 695 } 696 697 if (newVal != NULL) { 698 if (!PyObjCMethodSignature_Check(newVal)) { 699 PyErr_SetString(PyExc_TypeError, "New value must be a method signature"); 700 return -1; 701 } 702 } 703 704 PyObject* v = (PyObject*)PyObjCObject_GetBlock(self); 705 if (v != NULL) { 706 Py_DECREF(v); 707 } 708 709 710 Py_XINCREF(newVal); 711 PyObjCObject_SET_BLOCK(self, (PyObjCMethodSignature*)newVal); 712 return 0; 713} 714 715 716static PyGetSetDef obj_getset[] = { 717 { 718 "pyobjc_ISA", 719 objc_get_real_class, 720 NULL, 721 objc_get_real_class_doc, 722 0 723 }, 724 { 725 "pyobjc_instanceMethods", 726 obj_get_instanceMethods, 727 NULL, 728 obj_get_instanceMethods_doc, 729 0 730 }, 731 { 732 "__block_signature__", 733 obj_get_blocksignature, 734 obj_set_blocksignature, 735 "Call signature for a block, or None", 736 0 737 }, 738 { 0, 0, 0, 0, 0 } 739}; 740 741/* 742 * We don't support pickling of Objective-C objects at the moment. The new 743 * version 2 of the pickle protocol has a default pickle method for new-style 744 * classes that doesn't work for us (it will write incomplete values to the 745 * pickle). This method forces a failure during pickling. 746 */ 747static PyObject* 748meth_reduce(PyObject* self __attribute__((__unused__))) 749{ 750 PyErr_SetString(PyExc_TypeError, 751 "Cannot pickle Objective-C objects"); 752 return NULL; 753} 754 755static PyObject* 756as_cobject(PyObject* self) 757{ 758 if (PyObjCObject_GetObject(self) == nil) { 759 Py_INCREF(Py_None); 760 return Py_None; 761 } 762 return PyCapsule_New(PyObjCObject_GetObject(self), "objc.__object__", NULL); 763} 764 765static PyObject* 766get_c_void_p(void) 767{ 768static PyObject* c_void_p = NULL; 769 if (c_void_p == NULL) { 770 PyObject* mod_ctypes = PyImport_ImportModule("ctypes"); 771 if (mod_ctypes == NULL) { 772 /* ctypes is nota available */ 773 return NULL; 774 } 775 c_void_p = PyObject_GetAttrString(mod_ctypes, "c_void_p"); 776 Py_DECREF(mod_ctypes); 777 if (c_void_p == NULL) { 778 /* invalid or incomplete module */ 779 return NULL; 780 } 781 } 782 return c_void_p; 783} 784 785static PyObject* 786as_ctypes_voidp(PyObject* self) 787{ 788 PyObject* c_void_p; 789 790 if (PyObjCObject_GetObject(self) == nil) { 791 Py_INCREF(Py_None); 792 return Py_None; 793 } 794 795 c_void_p = get_c_void_p(); 796 if (c_void_p == NULL) { 797 return NULL; 798 } 799 800 return PyObject_CallFunction(c_void_p, "k", (long)PyObjCObject_GetObject(self)); 801} 802 803 804 805 806static PyMethodDef obj_methods[] = { 807 { 808 "__reduce__", 809 (PyCFunction)meth_reduce, 810 METH_NOARGS, 811 "Used for pickling" 812 }, 813 { 814 "__cobject__", 815 (PyCFunction)as_cobject, 816 METH_NOARGS, 817 "Return a CObject representing this object" 818 }, 819 { 820 "__c_void_p__", 821 (PyCFunction)as_ctypes_voidp, 822 METH_NOARGS, 823 "Return a ctypes.c_void_p representing this object" 824 }, 825 { 826 NULL, 827 NULL, 828 0, 829 NULL 830 } 831}; 832 833 834PyObjCClassObject PyObjCObject_Type = { 835 { 836 { 837 PyVarObject_HEAD_INIT(&PyObjCClass_Type, 0) 838 "objc_object", /* tp_name */ 839 sizeof(PyObjCObject), /* tp_basicsize */ 840 0, /* tp_itemsize */ 841 /* methods */ 842 object_dealloc, /* tp_dealloc */ 843 0, /* tp_print */ 844 0, /* tp_getattr */ 845 0, /* tp_setattr */ 846 0, /* tp_compare */ 847 object_repr, /* tp_repr */ 848 0, /* tp_as_number */ 849 0, /* tp_as_sequence */ 850 0, /* tp_as_mapping */ 851 0, /* tp_hash */ 852 0, /* tp_call */ 853 0, /* tp_str */ 854 object_getattro, /* tp_getattro */ 855 object_setattro, /* tp_setattro */ 856 0, /* tp_as_buffer */ 857 Py_TPFLAGS_DEFAULT 858 | Py_TPFLAGS_BASETYPE, /* tp_flags */ 859 0, /* tp_doc */ 860 0, /* tp_traverse */ 861 0, /* tp_clear */ 862 0, /* tp_richcompare */ 863 0, /* tp_weaklistoffset */ 864 0, /* tp_iter */ 865 0, /* tp_iternext */ 866 obj_methods, /* tp_methods */ 867 0, /* tp_members */ 868 obj_getset, /* tp_getset */ 869 0, /* tp_base */ 870 0, /* tp_dict */ 871 0, /* tp_descr_get */ 872 0, /* tp_descr_set */ 873 0, /* tp_dictoffset */ 874 0, /* tp_init */ 875 PyType_GenericAlloc, /* tp_alloc */ 876 object_new, /* tp_new */ 877 0, /* tp_free */ 878 0, /* tp_is_gc */ 879 0, /* tp_bases */ 880 0, /* tp_mro */ 881 0, /* tp_cache */ 882 0, /* tp_subclasses */ 883 0, /* tp_weaklist */ 884 (destructor)object_del /* tp_del */ 885 886#if PY_VERSION_HEX >= 0x02060000 887 , 0 /* tp_version_tag */ 888#endif 889 890 }, 891#if PY_MAJOR_VERSION == 2 892 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 893 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 894#if PY_VERSION_HEX >= 0x02050000 895 , 0 896#endif 897 }, /* as_number */ 898 { 0, 0, 0 }, /* as_mapping */ 899 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* as_sequence */ 900 { 0, 0, 0, 0 901#if PY_VERSION_HEX >= 0x02060000 902 , 0, 0 903#endif 904 }, /* as_buffer */ 905 0, /* name */ 906 0, /* slots */ 907#else /* Python 3 */ 908 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 909 }, /* as_number */ 910 { 0,0,0 911 }, /* as_mapping */ 912 { 0,0,0,0,0,0,0,0,0,0 913 }, /* as_sequence */ 914 { 0,0 915 }, /* as_buffer */ 916 0, 0 /* ht_name, ht_slots */ 917#if PY_VERSION_HEX >= 0x03030000 918 , 0, 0 /* ht_qualname, ht_cached_keys */ 919#endif 920 921 922#endif /* Python 3 */ 923 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 924}; 925 926/* 927 * Allocate a proxy object for use during the call of __del__, 928 * this isn't a full-featured proxy object. 929 */ 930PyObject* 931_PyObjCObject_NewDeallocHelper(id objc_object) 932{ 933 PyObject* res; 934 PyTypeObject* cls_type; 935 936 assert(objc_object != nil); 937 cls_type = (PyTypeObject*)PyObjCClass_New(object_getClass(objc_object)); 938 if (cls_type == NULL) { 939 return NULL; 940 } 941 942 res = cls_type->tp_alloc(cls_type, 0); 943 Py_DECREF(cls_type); 944 if (res == NULL) { 945 return NULL; 946 } 947 948 PyObjCClass_CheckMethodList((PyObject*)Py_TYPE(res), 1); 949 950 ((PyObjCObject*)res)->objc_object = objc_object; 951 ((PyObjCObject*)res)->flags = PyObjCObject_kDEALLOC_HELPER; 952 return res; 953} 954 955void 956_PyObjCObject_FreeDeallocHelper(PyObject* obj) 957{ 958 if (Py_REFCNT(obj) != 1) { 959 /* Someone revived this object. Objective-C doesn't like 960 * this at all, therefore warn the user about this and 961 * zero out the instance. 962 */ 963 char buf[256]; 964 snprintf(buf, sizeof(buf), 965 "revived Objective-C object of type %s. Object is zero-ed out.", 966 Py_TYPE(obj)->tp_name); 967 968 PyErr_Warn(PyObjCExc_ObjCRevivalWarning, buf); 969 970 id objc_object = PyObjCObject_GetObject(obj); 971 972 /* XXX: release the object */ 973 if (((PyObjCObject*)obj)->flags & PyObjCObject_kSHOULD_NOT_RELEASE) { 974 /* pass */ 975 } else if (((PyObjCObject*)obj)->flags & PyObjCObject_kUNINITIALIZED) { 976 /* pass */ 977 } else { 978 CFRelease(objc_object); 979 } 980 981 PyObjC_UnregisterPythonProxy( 982 objc_object, obj); 983 ((PyObjCObject*)obj)->objc_object = nil; 984 985 Py_DECREF(obj); 986 987 return; 988 } 989 Py_DECREF(obj); 990} 991 992 993PyObject* 994PyObjCObject_New(id objc_object, int flags, int retain) 995{ 996 Class cls = object_getClass(objc_object); 997 PyTypeObject* cls_type; 998 PyObject* res; 999 1000 res = PyObjC_FindPythonProxy(objc_object); 1001 if (res) return res; 1002 1003 assert(objc_object != nil); 1004 1005 cls_type = (PyTypeObject*)PyObjCClass_New(cls); 1006 if (cls_type == NULL) { 1007 return NULL; 1008 } 1009 1010 res = cls_type->tp_alloc(cls_type, 0); 1011 Py_DECREF(cls_type); 1012 if (res == NULL) { 1013 return NULL; 1014 } 1015 1016 if (cls_type->tp_basicsize == sizeof(PyObjCBlockObject)) { 1017 flags |= PyObjCObject_kBLOCK; 1018 } 1019 1020 /* This should be in the tp_alloc for the new class, but 1021 * adding a tp_alloc to PyObjCClass_Type doesn't seem to help 1022 */ 1023 PyObjCClass_CheckMethodList((PyObject*)Py_TYPE(res), 1); 1024 1025 ((PyObjCObject*)res)->objc_object = objc_object; 1026 ((PyObjCObject*)res)->flags = flags; 1027 1028 if (flags & PyObjCObject_kBLOCK) { 1029 ((PyObjCBlockObject*)res)->signature = NULL; 1030 } 1031 1032 if (retain) { 1033 if (strcmp(object_getClassName(objc_object), 1034 "NSAutoreleasePool") != 0) { 1035 /* NSAutoreleasePool doesn't like retain */ 1036 CFRetain(objc_object); 1037 } 1038 } 1039 1040 /* 1041 * Don't register if we use the default flags, other parts will do 1042 * that if necessary. I don't like this, but don't want to pollute 1043 * the interface of this function with yet another argument. 1044 */ 1045 if (flags != PyObjCObject_kDEFAULT) { 1046 PyObjC_RegisterPythonProxy(objc_object, res); 1047 } 1048 return res; 1049} 1050 1051PyObject* 1052PyObjCObject_FindSelector(PyObject* object, SEL selector) 1053{ 1054 PyObject* meth; 1055 1056 meth = PyObjCClass_FindSelector((PyObject*)Py_TYPE(object), selector, NO); 1057 1058 if (meth == NULL) { 1059 return NULL; 1060 } else { 1061 return meth; 1062 } 1063} 1064 1065id 1066(PyObjCObject_GetObject)(PyObject* object) 1067{ 1068 if (!PyObjCObject_Check(object)) { 1069 PyErr_Format(PyExc_TypeError, 1070 "'objc.objc_object' expected, got '%s'", 1071 Py_TYPE(object)->tp_name); 1072 1073 } 1074 return PyObjCObject_GetObject(object); 1075} 1076 1077void 1078PyObjCObject_ClearObject(PyObject* object) 1079{ 1080 if (!PyObjCObject_Check(object)) { 1081 PyErr_Format(PyExc_TypeError, 1082 "'objc.objc_object' expected, got '%s'", 1083 Py_TYPE(object)->tp_name); 1084 1085 } 1086 PyObjC_UnregisterPythonProxy( 1087 ((PyObjCObject*)object)->objc_object, object); 1088 ((PyObjCObject*)object)->objc_object = nil; 1089} 1090 1091PyObject* PyObjCObject_GetAttr(PyObject* obj, PyObject* name) 1092{ 1093 return object_getattro(obj, name); 1094} 1095 1096 1097PyObject* PyObjCObject_GetAttrString(PyObject* obj, char* name) 1098{ 1099 PyObject* pyname = PyText_FromString(name); 1100 if (pyname == NULL) return NULL; 1101 1102 PyObject* rv = object_getattro(obj, pyname); 1103 Py_DECREF(pyname); 1104 return rv; 1105} 1106