1/* 2 * alloc_hack.m -- Implementation of alloc_hack.h 3 */ 4#include "pyobjc.h" 5 6static PyObject* 7call_NSObject_alloc(PyObject* method, 8 PyObject* self, PyObject* arguments) 9{ 10 id result = nil; 11 struct objc_super spr; 12 IMP anIMP; 13 Class aClass; 14 SEL volatile aSel; 15 16 if (unlikely(PyArg_ParseTuple(arguments, "") < 0)) { 17 return NULL; 18 } 19 20 if (unlikely(!PyObjCClass_Check(self))) { 21 PyErr_Format(PyExc_TypeError, "Expecting Objective-C class, got instance of '%s'", Py_TYPE(self)->tp_name); 22 return NULL; 23 } 24 25 if (unlikely(PyObjCIMP_Check(method))) { 26 anIMP = PyObjCIMP_GetIMP(method); 27 aClass = PyObjCClass_GetClass(self); 28 aSel = PyObjCIMP_GetSelector(method); 29 30 PyObjC_DURING 31 result = anIMP(aClass, aSel); 32 33 PyObjC_HANDLER 34 PyObjCErr_FromObjC(localException); 35 result = nil; 36 37 PyObjC_ENDHANDLER; 38 39 } else { 40 objc_superSetReceiver(spr, (id)PyObjCClass_GetClass(self)); 41 objc_superSetClass(spr, object_getClass(PyObjCSelector_GetClass(method))); 42 aSel = PyObjCSelector_GetSelector(method); 43 44 PyObjC_DURING 45 result = objc_msgSendSuper(&spr, aSel); 46 47 PyObjC_HANDLER 48 PyObjCErr_FromObjC(localException); 49 result = nil; 50 51 PyObjC_ENDHANDLER; 52 } 53 54 if (unlikely(result == nil && PyErr_Occurred())) { 55 return NULL; 56 } 57 58 return PyObjCObject_New(result, PyObjCObject_kUNINITIALIZED, NO); 59} 60 61static void 62imp_NSObject_alloc( 63 ffi_cif* cif __attribute__((__unused__)), 64 void* resp, 65 void** args __attribute__((__unused__)), 66 void* callable) 67{ 68 int err; 69 PyObject* arglist = NULL; 70 PyObject* v = NULL; 71 PyObject* result = NULL; 72 73 PyObjC_BEGIN_WITH_GIL 74 75 arglist = PyTuple_New(1); 76 if (unlikely(arglist == NULL)) { 77 PyObjC_GIL_FORWARD_EXC(); 78 } 79 80 v = PyObjC_IdToPython(*(id*)args[0]); 81 if (unlikely(v == NULL)) { 82 Py_DECREF(arglist); 83 PyObjC_GIL_FORWARD_EXC(); 84 } 85 v = PyObjC_AdjustSelf(v); 86 if (unlikely(v == NULL)) { 87 Py_DECREF(arglist); 88 PyObjC_GIL_FORWARD_EXC(); 89 } 90 91 PyTuple_SET_ITEM(arglist, 0, v); 92 v = NULL; 93 94 result = PyObject_Call((PyObject*)callable, arglist, NULL); 95 if (unlikely(result == NULL)) { 96 Py_DECREF(arglist); 97 PyObjC_GIL_FORWARD_EXC(); 98 } 99 100 Py_DECREF(arglist); 101 102 err = depythonify_c_value(@encode(id), result, resp); 103 Py_DECREF(result); 104 if (unlikely(err == -1)) { 105 PyObjC_GIL_FORWARD_EXC(); 106 } 107 108 PyObjC_END_WITH_GIL 109} 110 111static PyObject* 112call_NSObject_dealloc(PyObject* method, 113 PyObject* self, PyObject* arguments) 114{ 115 struct objc_super spr; 116 IMP anIMP; 117 Class aClass; 118 SEL volatile aSel; 119 120 if (unlikely(PyArg_ParseTuple(arguments, "") < 0)) { 121 return NULL; 122 } 123 124 if (unlikely(!PyObjCObject_Check(self))) { 125 PyErr_Format(PyExc_TypeError, 126 "[dealloc] Expecting Objective-C instance, got instance of '%s'", 127 Py_TYPE(self)->tp_name); 128 return NULL; 129 } 130 131 if (unlikely(PyObjCIMP_Check(method))) { 132 anIMP = PyObjCIMP_GetIMP(method); 133 aClass = PyObjCClass_GetClass(self); 134 aSel = PyObjCIMP_GetSelector(method); 135 136 PyObjC_DURING 137 (void)anIMP(aClass, aSel); 138 139 PyObjC_HANDLER 140 PyObjCErr_FromObjC(localException); 141 142 PyObjC_ENDHANDLER; 143 144 } else { 145 objc_superSetReceiver(spr, PyObjCObject_GetObject(self)); 146 objc_superSetClass(spr, PyObjCSelector_GetClass(method)); 147 aSel = PyObjCSelector_GetSelector(method); 148 149 PyObjC_DURING 150 (void)objc_msgSendSuper(&spr, aSel); 151 152 PyObjC_HANDLER 153 PyObjCErr_FromObjC(localException); 154 155 PyObjC_ENDHANDLER; 156 } 157 158 PyObjCObject_ClearObject(self); 159 160 if (unlikely(PyErr_Occurred())) { 161 return NULL; 162 } 163 164 165 Py_INCREF(Py_None); 166 return Py_None; 167} 168 169static void 170imp_NSObject_dealloc( 171 ffi_cif* cif __attribute__((__unused__)), 172 void* resp __attribute__((__unused__)), 173 void** args __attribute__((__unused__)), 174 void* callable) 175{ 176 PyObject* arglist = NULL; 177 PyObject* v = NULL; 178 PyObject* result = NULL; 179 180 PyObjC_BEGIN_WITH_GIL 181 182 arglist = PyTuple_New(1); 183 if (unlikely(arglist == NULL)) { 184 PyObjC_GIL_FORWARD_EXC(); 185 } 186 187 v = PyObjC_IdToPython(*(id*)args[0]); 188 if (unlikely(v == NULL)) { 189 Py_DECREF(arglist); 190 PyObjC_GIL_FORWARD_EXC(); 191 } 192 193 PyTuple_SET_ITEM(arglist, 0, v); 194 v = NULL; 195 196 result = PyObject_Call((PyObject*)callable, arglist, NULL); 197 if (unlikely(result == NULL)) { 198 Py_DECREF(arglist); 199 PyObjC_GIL_FORWARD_EXC(); 200 } 201 202 Py_DECREF(arglist); 203 204 if (unlikely(result != Py_None)) { 205 PyErr_Format(PyExc_TypeError, 206 "dealloc should return None, returned instance" 207 " of %s", Py_TYPE(result)->tp_name); 208 PyObjC_GIL_FORWARD_EXC(); 209 } 210 211 Py_DECREF(result); 212 213 PyObjC_END_WITH_GIL 214} 215 216static PyObject* 217call_NSObject_release(PyObject* method, 218 PyObject* self, PyObject* arguments) 219{ 220 struct objc_super spr; 221 IMP anIMP; 222 Class aClass; 223 SEL volatile aSel; 224 225 if (unlikely(PyArg_ParseTuple(arguments, "") < 0)) { 226 return NULL; 227 } 228 229 if (unlikely(!PyObjCObject_Check(self))) { 230 PyErr_Format(PyExc_TypeError, 231 "[release] Expecting Objective-C instance, got instance of '%s'", 232 Py_TYPE(self)->tp_name); 233 return NULL; 234 } 235 236 if (unlikely(PyObjCIMP_Check(method))) { 237 anIMP = PyObjCIMP_GetIMP(method); 238 aClass = PyObjCClass_GetClass(self); 239 aSel = PyObjCIMP_GetSelector(method); 240 241 PyObjC_DURING 242 (void)anIMP(aClass, aSel); 243 244 PyObjC_HANDLER 245 PyObjCErr_FromObjC(localException); 246 247 PyObjC_ENDHANDLER; 248 249 } else { 250 objc_superSetReceiver(spr, PyObjCObject_GetObject(self)); 251 objc_superSetClass(spr, PyObjCSelector_GetClass(method)); 252 aSel = PyObjCSelector_GetSelector(method); 253 254 PyObjC_DURING 255 (void)objc_msgSendSuper(&spr, aSel); 256 257 PyObjC_HANDLER 258 PyObjCErr_FromObjC(localException); 259 260 PyObjC_ENDHANDLER; 261 } 262 263 if (unlikely(PyErr_Occurred())) { 264 return NULL; 265 } 266 267 268 Py_INCREF(Py_None); 269 return Py_None; 270} 271 272static PyObject* 273call_NSObject_retain(PyObject* method, 274 PyObject* self, PyObject* arguments) 275{ 276 struct objc_super spr; 277 IMP anIMP; 278 Class aClass; 279 SEL volatile aSel; 280 volatile id retval = nil; 281 282 if (unlikely(PyArg_ParseTuple(arguments, "") < 0)) { 283 return NULL; 284 } 285 286 if (!PyObjCObject_Check(self)) { 287 PyErr_Format(PyExc_TypeError, 288 "[retain] Expecting Objective-C instance, got instance of '%s'", 289 Py_TYPE(self)->tp_name); 290 return NULL; 291 } 292 293 if (PyObjCIMP_Check(method)) { 294 anIMP = PyObjCIMP_GetIMP(method); 295 aClass = PyObjCClass_GetClass(self); 296 aSel = PyObjCIMP_GetSelector(method); 297 298 PyObjC_DURING 299 retval = anIMP(aClass, aSel); 300 301 PyObjC_HANDLER 302 PyObjCErr_FromObjC(localException); 303 304 PyObjC_ENDHANDLER; 305 306 } else { 307 objc_superSetReceiver(spr, PyObjCObject_GetObject(self)); 308 objc_superSetClass(spr, PyObjCSelector_GetClass(method)); 309 aSel = PyObjCSelector_GetSelector(method); 310 311 PyObjC_DURING 312 retval = objc_msgSendSuper(&spr, aSel); 313 314 PyObjC_HANDLER 315 PyObjCErr_FromObjC(localException); 316 317 PyObjC_ENDHANDLER; 318 } 319 320 if (PyErr_Occurred()) { 321 return NULL; 322 } 323 324 return PyObjC_IdToPython(retval); 325} 326 327static void 328imp_NSObject_release( 329 ffi_cif* cif __attribute__((__unused__)), 330 void* resp __attribute__((__unused__)), 331 void** args __attribute__((__unused__)), 332 void* callable) 333{ 334 PyObject* arglist = NULL; 335 PyObject* result = NULL; 336 PyObject* pyself; 337 int cookie; 338 339 PyObjC_BEGIN_WITH_GIL 340 341 arglist = PyTuple_New(1); 342 if (arglist == NULL) { 343 PyObjC_GIL_FORWARD_EXC(); 344 } 345 346 pyself = PyObjCObject_NewTransient(*(id*)args[0], &cookie); 347 if (pyself == NULL) { 348 Py_DECREF(arglist); 349 PyObjC_GIL_FORWARD_EXC(); 350 } 351 352 PyTuple_SET_ITEM(arglist, 0, pyself); 353 Py_INCREF(pyself); 354 355 result = PyObject_Call((PyObject*)callable, arglist, NULL); 356 if (result == NULL) { 357 Py_DECREF(arglist); 358 PyObjCObject_ReleaseTransient(pyself, cookie); 359 PyObjC_GIL_FORWARD_EXC(); 360 } 361 362 Py_DECREF(arglist); 363 PyObjCObject_ReleaseTransient(pyself, cookie); 364 365 if (result != Py_None) { 366 PyErr_Format(PyExc_TypeError, 367 "release should return None, returned instance" 368 " of %s", Py_TYPE(result)->tp_name); 369 PyObjC_GIL_FORWARD_EXC(); 370 } 371 372 Py_DECREF(result); 373 374 PyObjC_END_WITH_GIL 375} 376 377static void 378imp_NSObject_retain( 379 ffi_cif* cif __attribute__((__unused__)), 380 void* resp __attribute__((__unused__)), 381 void** args __attribute__((__unused__)), 382 void* callable) 383{ 384 PyObject* arglist = NULL; 385 PyObject* result = NULL; 386 PyObject* pyself; 387 int cookie; 388 int err; 389 390 PyObjC_BEGIN_WITH_GIL 391 392 arglist = PyTuple_New(1); 393 if (arglist == NULL) { 394 PyObjC_GIL_FORWARD_EXC(); 395 } 396 397 pyself = PyObjCObject_NewTransient(*(id*)args[0], &cookie); 398 if (pyself == NULL) { 399 Py_DECREF(arglist); 400 PyObjC_GIL_FORWARD_EXC(); 401 } 402 403 PyTuple_SET_ITEM(arglist, 0, pyself); 404 Py_INCREF(pyself); 405 406 result = PyObject_Call((PyObject*)callable, arglist, NULL); 407 if (result == NULL) { 408 Py_DECREF(arglist); 409 PyObjCObject_ReleaseTransient(pyself, cookie); 410 PyObjC_GIL_FORWARD_EXC(); 411 } 412 413 Py_DECREF(arglist); 414 415 err = depythonify_c_value(@encode(id), result, resp); 416 Py_DECREF(result); 417 PyObjCObject_ReleaseTransient(pyself, cookie); 418 if (err == -1) { 419 PyObjC_GIL_FORWARD_EXC(); 420 } 421 422 PyObjC_END_WITH_GIL 423} 424 425 426int 427PyObjC_InstallAllocHack(void) 428{ 429 int r; 430 431 r = PyObjC_RegisterMethodMapping( 432 objc_lookUpClass("NSObject"), 433 @selector(alloc), 434 call_NSObject_alloc, 435 imp_NSObject_alloc); 436 if (r != 0) return r; 437 438 r = PyObjC_RegisterMethodMapping( 439 objc_lookUpClass("NSObject"), 440 @selector(dealloc), 441 call_NSObject_dealloc, 442 imp_NSObject_dealloc); 443 if (r != 0) return r; 444 445 r = PyObjC_RegisterMethodMapping( 446 objc_lookUpClass("NSObject"), 447 @selector(retain), 448 call_NSObject_retain, 449 imp_NSObject_retain); 450 if (r != 0) return r; 451 452 r = PyObjC_RegisterMethodMapping( 453 objc_lookUpClass("NSObject"), 454 @selector(release), 455 call_NSObject_release, 456 imp_NSObject_release); 457 if (r != 0) return r; 458 459 return r; 460} 461