| 1402 | } |
| 1403 | |
| 1404 | extern "C" PyObject *GetCurrentGlobalHandle() |
| 1405 | { |
| 1406 | PyObject *frame_global_handle = NULL; |
| 1407 | |
| 1408 | // walk the frames until we find one with _renderdoc_internal. If we call a function in another |
| 1409 | // module the globals may not have the entry, but the root level is expected to. |
| 1410 | { |
| 1411 | PyFrameObject *frame = PyEval_GetFrame(); |
| 1412 | // inc reference count here so all frames can be decref'd whether they come from here or |
| 1413 | // PyFrame_GetBack |
| 1414 | Py_XINCREF(frame); |
| 1415 | |
| 1416 | while(frame) |
| 1417 | { |
| 1418 | PyObject *globals = PyFrame_GetGlobals(frame); |
| 1419 | frame_global_handle = PyDict_GetItemString(globals, "_renderdoc_internal"); |
| 1420 | Py_XDECREF(globals); |
| 1421 | |
| 1422 | // first get the next frame without decrefing the current |
| 1423 | PyFrameObject *back = PyFrame_GetBack(frame); |
| 1424 | // now decref the old frame |
| 1425 | Py_XDECREF(frame); |
| 1426 | // and iterate on the next one, if we got one |
| 1427 | frame = back; |
| 1428 | |
| 1429 | if(frame_global_handle) |
| 1430 | { |
| 1431 | // release the last trailing ref, which we know is either NULL or a strong reference from |
| 1432 | // PyFrame_GetBack |
| 1433 | Py_XDECREF(frame); |
| 1434 | break; |
| 1435 | } |
| 1436 | } |
| 1437 | } |
| 1438 | |
| 1439 | if(frame_global_handle) |
| 1440 | return frame_global_handle; |
| 1441 | |
| 1442 | if(current_global_handle) |
| 1443 | return current_global_handle; |
| 1444 | |
| 1445 | PyObject *sys = PyImport_ImportModule("sys"); |
| 1446 | if(sys) |
| 1447 | { |
| 1448 | PyObject *ret = PyObject_SafeGetAttrString(sys, "_renderdoc_internal"); |
| 1449 | |
| 1450 | Py_XDECREF(sys); |
| 1451 | Py_XDECREF(ret); |
| 1452 | return ret; |
| 1453 | } |
| 1454 | |
| 1455 | return NULL; |
| 1456 | } |
| 1457 | |
| 1458 | extern "C" void HandleException(PyObject *global_handle) |
| 1459 | { |
no test coverage detected