PyObject *PythonModules::loadModule(QString modulePath, bool reload, bool *firstLoad) { PyObject *pModule = nullptr; if (modulePath.isEmpty()) { // should have been checked earlier already, but who knows ... callback->logError(tr("Empty module path name, nothing to load...")); return pModule; } PyGILState_STATE lgstate; lgstate = PyGILState_Ensure(); if (!modulesPath.contains(modulePath)) { qDebug() << "Instanciating the module for the first time " << modulePath; QString moduleName = getModuleNameFromFile(modulePath); if (!checkModuleNameAndPath(modulePath, moduleName)) { // checking if the module is already there from another file PyGILState_Release(lgstate); return pModule; } pModule = PyImport_ImportModule(moduleName.toUtf8().data()); // new reference if (!checkPyError()) { callback->logError(tr("Module \"%1\" could not be loaded:\n %2").arg(modulePath).arg(errorMessage)); pModule = nullptr; } else { if (!checkModuleNameAndPath(modulePath, moduleName)) { // checking if the module loaded comes from the file that was supplied Py_XDECREF(pModule); pModule = nullptr; PyGILState_Release(lgstate); return pModule; } if (PyObject_HasAttrString(pModule, MAIN_FUNCTION_NAME) != 1) { callback->logError(tr("The python module %2 does not have the %1 method").arg(QString::fromUtf8(MAIN_FUNCTION_NAME)).arg(moduleName)); Py_XDECREF(pModule); pModule = nullptr; PyGILState_Release(lgstate); return pModule; } else { modulesPath.insert(modulePath,pModule); if (firstLoad != nullptr) *firstLoad = true; } } } else if (reload) { qDebug() << "Reloading module" << modulePath; PyObject *oldModule = modulesPath.take(modulePath); // the module object is either going to be replaced or cleared // clearing global objects (we don't care about any error message here) PyObject * attr = PyObject_GetAttrString(oldModule,INBOUND_ATTR_NAME); PyErr_Clear(); Py_XDECREF(attr); attr = PyObject_GetAttrString(oldModule,ISTWOWAY_ATTR_NAME); PyErr_Clear(); Py_XDECREF(attr); attr = PyObject_GetAttrString(oldModule,PARAMS_ATTR_NAME); PyErr_Clear(); Py_XDECREF(attr); attr = PyObject_GetAttrString(oldModule,PARAMS_NAMES_ATTR_NAME); PyErr_Clear(); Py_XDECREF(attr); // reloading pModule = PyImport_ReloadModule(oldModule); // new ref ?? if (pModule != oldModule) { Py_XDECREF(oldModule); // clearing the old module object if the new ref is different } if (!checkPyError()) { callback->logError(tr("Error(s) while reloading the module %1, removing it from the the registered modules.\n%2").arg(modulePath).arg(errorMessage)); pModule = nullptr; } else { modulesPath.insert(modulePath,pModule); } } else { qDebug() << "no reload, taking the module as it is already" << modulePath; pModule = modulesPath.value(modulePath); } PyGILState_Release(lgstate); return pModule; }
void PythonHostEnvironment::prepareCallbackFinish(void* state) { PyGILState_STATE* state2 = (PyGILState_STATE*)state; PyGILState_Release(*state2); delete state2; }
~PyThreadStateLock(void) { #ifndef KBE_SINGLE_THREADED PyGILState_Release( state ); #endif }
~PyGilStateLock(void){PyGILState_Release(_s);}
int yara_callback( int message, YR_RULE* rule, void* data) { YR_STRING* string; YR_MATCH* m; YR_META* meta; char* tag_name; size_t tag_length; PyObject* tag_list = NULL; PyObject* string_list = NULL; PyObject* meta_list = NULL; PyObject* match; PyObject* callback_dict; PyObject* object; PyObject* tuple; PyObject* matches = ((CALLBACK_DATA*) data)->matches; PyObject* callback = ((CALLBACK_DATA*) data)->callback; PyObject* callback_result; PyGILState_STATE gil_state; int result = CALLBACK_CONTINUE; if (message == CALLBACK_MSG_SCAN_FINISHED) return CALLBACK_CONTINUE; if (message == CALLBACK_MSG_RULE_NOT_MATCHING && callback == NULL) return CALLBACK_CONTINUE; gil_state = PyGILState_Ensure(); tag_list = PyList_New(0); string_list = PyList_New(0); meta_list = PyDict_New(); if (tag_list == NULL || string_list == NULL || meta_list == NULL) { Py_XDECREF(tag_list); Py_XDECREF(string_list); Py_XDECREF(meta_list); PyGILState_Release(gil_state); return CALLBACK_ERROR; } tag_name = rule->tags; tag_length = tag_name != NULL ? strlen(tag_name) : 0; while (tag_length > 0) { object = PY_STRING(tag_name); PyList_Append(tag_list, object); Py_DECREF(object); tag_name += tag_length + 1; tag_length = strlen(tag_name); } meta = rule->metas; while(!META_IS_NULL(meta)) { if (meta->type == META_TYPE_INTEGER) object = Py_BuildValue("I", meta->integer); else if (meta->type == META_TYPE_BOOLEAN) object = PyBool_FromLong(meta->integer); else object = PY_STRING(meta->string); PyDict_SetItemString(meta_list, meta->identifier, object); Py_DECREF(object); meta++; } string = rule->strings; while (!STRING_IS_NULL(string)) { if (STRING_FOUND(string)) { m = STRING_MATCHES(string).head; while (m != NULL) { object = PyBytes_FromStringAndSize((char*) m->data, m->length); tuple = Py_BuildValue( "(L,s,O)", m->offset, string->identifier, object); PyList_Append(string_list, tuple); Py_DECREF(object); Py_DECREF(tuple); m = m->next; } } string++; } if (message == CALLBACK_MSG_RULE_MATCHING) { match = Match_NEW( rule->identifier, rule->ns->name, tag_list, meta_list, string_list); if (match != NULL) { PyList_Append(matches, match); Py_DECREF(match); } else { Py_DECREF(tag_list); Py_DECREF(string_list); Py_DECREF(meta_list); PyGILState_Release(gil_state); return CALLBACK_ERROR; } } if (callback != NULL) { Py_INCREF(callback); callback_dict = PyDict_New(); object = PyBool_FromLong(message == CALLBACK_MSG_RULE_MATCHING); PyDict_SetItemString(callback_dict, "matches", object); Py_DECREF(object); object = PY_STRING(rule->identifier); PyDict_SetItemString(callback_dict, "rule", object); Py_DECREF(object); object = PY_STRING(rule->ns->name); PyDict_SetItemString(callback_dict, "namespace", object); Py_DECREF(object); PyDict_SetItemString(callback_dict, "tags", tag_list); PyDict_SetItemString(callback_dict, "meta", meta_list); PyDict_SetItemString(callback_dict, "strings", string_list); callback_result = PyObject_CallFunctionObjArgs( callback, callback_dict, NULL); if (callback_result != NULL) { #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(callback_result)) #else if (PyLong_Check(callback_result) || PyInt_Check(callback_result)) #endif { result = (int) PyLong_AsLong(callback_result); } Py_DECREF(callback_result); } else { result = CALLBACK_ERROR; } Py_DECREF(callback_dict); Py_DECREF(callback); } Py_DECREF(tag_list); Py_DECREF(string_list); Py_DECREF(meta_list); PyGILState_Release(gil_state); return result; }
~AcquirePyGIL() { PyGILState_Release(state); }
void unlock() { PyGILState_Release(state_); }
/* * External interface */ static void DoPyCommand(const char *cmd, rangeinitializer init_range, runner run, void *arg) { #ifndef PY_CAN_RECURSE static int recursive = 0; #endif #if defined(MACOS) && !defined(MACOS_X_UNIX) GrafPtr oldPort; #endif #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) char *saved_locale; #endif #ifdef PY_CAN_RECURSE PyGILState_STATE pygilstate; #endif #ifndef PY_CAN_RECURSE if (recursive) { EMSG(_("E659: Cannot invoke Python recursively")); return; } ++recursive; #endif #if defined(MACOS) && !defined(MACOS_X_UNIX) GetPort(&oldPort); /* Check if the Python library is available */ if ((Ptr)PyMac_Initialize == (Ptr)kUnresolvedCFragSymbolAddress) goto theend; #endif if (Python_Init()) goto theend; init_range(arg); Python_Release_Vim(); /* leave vim */ #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) /* Python only works properly when the LC_NUMERIC locale is "C". */ saved_locale = setlocale(LC_NUMERIC, NULL); if (saved_locale == NULL || STRCMP(saved_locale, "C") == 0) saved_locale = NULL; else { /* Need to make a copy, value may change when setting new locale. */ saved_locale = (char *) PY_STRSAVE(saved_locale); (void)setlocale(LC_NUMERIC, "C"); } #endif #ifdef PY_CAN_RECURSE pygilstate = PyGILState_Ensure(); #else Python_RestoreThread(); /* enter python */ #endif run((char *) cmd, arg #ifdef PY_CAN_RECURSE , &pygilstate #endif ); #ifdef PY_CAN_RECURSE PyGILState_Release(pygilstate); #else Python_SaveThread(); /* leave python */ #endif #if defined(HAVE_LOCALE_H) || defined(X_LOCALE) if (saved_locale != NULL) { (void)setlocale(LC_NUMERIC, saved_locale); PyMem_Free(saved_locale); } #endif Python_Lock_Vim(); /* enter vim */ PythonIO_Flush(); #if defined(MACOS) && !defined(MACOS_X_UNIX) SetPort(oldPort); #endif theend: #ifndef PY_CAN_RECURSE --recursive; #endif return; }
void PythonContext::executeString(const QString &filename, const QString &source) { if(!initialised()) { emit exception( lit("SystemError"), tr("Python integration failed to initialise, see diagnostic log for more information."), -1, {}); return; } location.file = filename; location.line = 1; PyGILState_STATE gil = PyGILState_Ensure(); PyObject *compiled = Py_CompileString(source.toUtf8().data(), filename.toUtf8().data(), source.count(QLatin1Char('\n')) == 0 ? Py_single_input : Py_file_input); PyObject *ret = NULL; if(compiled) { PyObject *traceContext = PyDict_New(); uintptr_t thisint = (uintptr_t) this; uint64_t thisuint64 = (uint64_t)thisint; PyObject *thisobj = PyLong_FromUnsignedLongLong(thisuint64); PyDict_SetItemString(traceContext, "thisobj", thisobj); PyDict_SetItemString(traceContext, "compiled", compiled); PyEval_SetTrace(&PythonContext::traceEvent, traceContext); m_Abort = false; m_State = PyGILState_GetThisThreadState(); ret = PyEval_EvalCode(compiled, context_namespace, context_namespace); m_State = NULL; // catch any output outputTick(); PyEval_SetTrace(NULL, NULL); Py_XDECREF(thisobj); Py_XDECREF(traceContext); } Py_DecRef(compiled); QString typeStr; QString valueStr; int finalLine = -1; QList<QString> frames; bool caughtException = (ret == NULL); if(caughtException) FetchException(typeStr, valueStr, finalLine, frames); Py_XDECREF(ret); PyGILState_Release(gil); if(caughtException) emit exception(typeStr, valueStr, finalLine, frames); }
QStringList PythonContext::completionOptions(QString base) { QStringList ret; if(!m_Completer) return ret; QByteArray bytes = base.toUtf8(); const char *input = (const char *)bytes.data(); PyGILState_STATE gil = PyGILState_Ensure(); PyObject *completeFunction = PyObject_GetAttrString(m_Completer, "complete"); int idx = 0; PyObject *opt = NULL; do { opt = PyObject_CallFunction(completeFunction, "si", input, idx); if(opt && opt != Py_None) { QString optstr = ToQStr(opt); bool add = true; // little hack, remove some of the ugly swig template instantiations that we can't avoid. if(optstr.contains(lit("renderdoc.rdcarray")) || optstr.contains(lit("renderdoc.rdcstr")) || optstr.contains(lit("renderdoc.bytebuf"))) add = false; if(add) ret << optstr; } idx++; } while(opt && opt != Py_None); // extra hack, remove the swig object functions/data but ONLY if we find a sure-fire identifier // (thisown) since otherwise we could remove append from a list object bool containsSwigInternals = false; for(const QString &optstr : ret) { if(optstr.contains(lit(".thisown"))) { containsSwigInternals = true; break; } } if(containsSwigInternals) { for(int i = 0; i < ret.count();) { if(ret[i].endsWith(lit(".acquire(")) || ret[i].endsWith(lit(".append(")) || ret[i].endsWith(lit(".disown(")) || ret[i].endsWith(lit(".next(")) || ret[i].endsWith(lit(".own(")) || ret[i].endsWith(lit(".this")) || ret[i].endsWith(lit(".thisown"))) ret.removeAt(i); else i++; } } Py_DecRef(completeFunction); PyGILState_Release(gil); return ret; }
PythonContext::PythonContext(QObject *parent) : QObject(parent) { if(!initialised()) return; // acquire the GIL and make sure this thread is init'd PyGILState_STATE gil = PyGILState_Ensure(); // clone our own local context context_namespace = PyDict_Copy(main_dict); PyObject *rlcompleter = PyDict_GetItemString(main_dict, "rlcompleter"); // for compatibility with earlier versions of python that took a char * instead of const char * char noparams[1] = ""; // set global output that point to this context. It is responsible for deleting the context when // it goes out of scope PyObject *redirector = PyObject_CallFunction((PyObject *)&OutputRedirectorType, noparams); if(redirector) { PyDict_SetItemString(context_namespace, "_renderdoc_internal", redirector); OutputRedirector *output = (OutputRedirector *)redirector; output->context = this; Py_DECREF(redirector); } if(rlcompleter) { PyObject *Completer = PyObject_GetAttrString(rlcompleter, "Completer"); if(Completer) { // create a completer for our context's namespace m_Completer = PyObject_CallFunction(Completer, "O", context_namespace); if(m_Completer) { PyDict_SetItemString(context_namespace, "_renderdoc_completer", m_Completer); } else { QString typeStr; QString valueStr; int finalLine = -1; QList<QString> frames; FetchException(typeStr, valueStr, finalLine, frames); // failure is not fatal qWarning() << "Couldn't create completion object. " << typeStr << ": " << valueStr; PyErr_Clear(); } } Py_DecRef(Completer); } else { m_Completer = NULL; } // release the GIL again PyGILState_Release(gil); // every 100ms while running, check for new output outputTicker = new QTimer(this); outputTicker->setInterval(100); QObject::connect(outputTicker, &QTimer::timeout, this, &PythonContext::outputTick); // we have to start it here, because we can't start on another thread. outputTicker->start(); }
// Initialize the QML engine. void PyQt5QmlPlugin::initializeEngine(QQmlEngine *engine, const char *uri) { if (!Py_IsInitialized() || !py_plugin_obj || !sip) return; #ifdef WITH_THREAD PyGILState_STATE gil = PyGILState_Ensure(); #endif const sipTypeDef *td = sip->api_find_type("QQmlEngine"); if (!td) { PyErr_SetString(PyExc_AttributeError, "unable to find type for QQmlEngine"); } else { PyObject *engine_obj = sip->api_convert_from_type(engine, td, 0); if (!engine_obj) { td = 0; } else { PyObject *res_obj = PyObject_CallMethod(py_plugin_obj, const_cast<char *>("initializeEngine"), const_cast<char *>("Os"), engine_obj, uri); Py_DECREF(engine_obj); if (res_obj != Py_None) { if (res_obj) #if PY_MAJOR_VERSION >= 3 PyErr_Format(PyExc_TypeError, "unexpected result from initializeEngine(): %S", res_obj); #else { PyObject *res_s = PyObject_Str(res_obj); if (res_s != NULL) { PyErr_Format(PyExc_TypeError, "unexpected result from initializeEngine(): %s", PyString_AsString(res_s)); Py_DECREF(res_s); } } #endif td = 0; } Py_XDECREF(res_obj); } } if (!td) PyErr_Print(); #ifdef WITH_THREAD PyGILState_Release(gil); #endif }
int yara_callback( int message, void* message_data, void* user_data) { YR_STRING* string; YR_MATCH* m; YR_META* meta; YR_RULE* rule; YR_MODULE_IMPORT* module_import; const char* tag; PyObject* tag_list = NULL; PyObject* string_list = NULL; PyObject* meta_list = NULL; PyObject* match; PyObject* callback_dict; PyObject* object; PyObject* tuple; PyObject* matches = ((CALLBACK_DATA*) user_data)->matches; PyObject* callback = ((CALLBACK_DATA*) user_data)->callback; PyObject* modules_data = ((CALLBACK_DATA*) user_data)->modules_data; PyObject* modules_callback = ((CALLBACK_DATA*) user_data)->modules_callback; PyObject* module_data; PyObject* callback_result; PyObject* module_info_dict; Py_ssize_t data_size; PyGILState_STATE gil_state; int result = CALLBACK_CONTINUE; if (message == CALLBACK_MSG_SCAN_FINISHED) return CALLBACK_CONTINUE; if (message == CALLBACK_MSG_RULE_NOT_MATCHING && callback == NULL) return CALLBACK_CONTINUE; if (message == CALLBACK_MSG_IMPORT_MODULE && modules_data == NULL) return CALLBACK_CONTINUE; if (message == CALLBACK_MSG_MODULE_IMPORTED && modules_callback == NULL) return CALLBACK_CONTINUE; if (message == CALLBACK_MSG_IMPORT_MODULE) { gil_state = PyGILState_Ensure(); module_import = (YR_MODULE_IMPORT*) message_data; module_data = PyDict_GetItemString( modules_data, module_import->module_name); #if PY_MAJOR_VERSION >= 3 if (module_data != NULL && PyBytes_Check(module_data)) #else if (module_data != NULL && PyString_Check(module_data)) #endif { #if PY_MAJOR_VERSION >= 3 PyBytes_AsStringAndSize( module_data, (char**) &module_import->module_data, &data_size); #else PyString_AsStringAndSize( module_data, (char**) &module_import->module_data, &data_size); #endif module_import->module_data_size = data_size; } PyGILState_Release(gil_state); return CALLBACK_CONTINUE; } if (message == CALLBACK_MSG_MODULE_IMPORTED) { gil_state = PyGILState_Ensure(); module_info_dict = convert_structure_to_python( (YR_OBJECT_STRUCTURE*) message_data); if (module_info_dict == NULL) return CALLBACK_CONTINUE; object = PY_STRING(((YR_OBJECT_STRUCTURE*) message_data)->identifier); PyDict_SetItemString(module_info_dict, "module", object); Py_DECREF(object); Py_INCREF(modules_callback); callback_result = PyObject_CallFunctionObjArgs( modules_callback, module_info_dict, NULL); if (callback_result != NULL) { #if PY_MAJOR_VERSION >= 3 if (PyLong_Check(callback_result)) #else if (PyLong_Check(callback_result) || PyInt_Check(callback_result)) #endif { result = (int) PyLong_AsLong(callback_result); } Py_DECREF(callback_result); } else { result = CALLBACK_ERROR; } Py_DECREF(module_info_dict); Py_DECREF(modules_callback); PyGILState_Release(gil_state); return result; } rule = (YR_RULE*) message_data; gil_state = PyGILState_Ensure(); tag_list = PyList_New(0); string_list = PyList_New(0); meta_list = PyDict_New(); if (tag_list == NULL || string_list == NULL || meta_list == NULL) { Py_XDECREF(tag_list); Py_XDECREF(string_list); Py_XDECREF(meta_list); PyGILState_Release(gil_state); return CALLBACK_ERROR; } yr_rule_tags_foreach(rule, tag) { object = PY_STRING(tag); PyList_Append(tag_list, object); Py_DECREF(object); }
inline ~gil_holder() { PyGILState_Release(gil_state); }
extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *cam_frame, int always_use_expand_framing) { /* context values */ struct wmWindowManager *wm= CTX_wm_manager(C); struct wmWindow *win= CTX_wm_window(C); struct Scene *startscene= CTX_data_scene(C); struct Main* maggie1= CTX_data_main(C); RAS_Rect area_rect; area_rect.SetLeft(cam_frame->xmin); area_rect.SetBottom(cam_frame->ymin); area_rect.SetRight(cam_frame->xmax); area_rect.SetTop(cam_frame->ymax); int exitrequested = KX_EXIT_REQUEST_NO_REQUEST; Main* blenderdata = maggie1; char* startscenename = startscene->id.name+2; char pathname[FILE_MAXDIR+FILE_MAXFILE], oldsce[FILE_MAXDIR+FILE_MAXFILE]; STR_String exitstring = ""; BlendFileData *bfd= NULL; BLI_strncpy(pathname, blenderdata->name, sizeof(pathname)); BLI_strncpy(oldsce, G.main->name, sizeof(oldsce)); #ifdef WITH_PYTHON resetGamePythonPath(); // need this so running a second time wont use an old blendfiles path setGamePythonPath(G.main->name); // Acquire Python's GIL (global interpreter lock) // so we can safely run Python code and API calls PyGILState_STATE gilstate = PyGILState_Ensure(); PyObject *pyGlobalDict = PyDict_New(); /* python utility storage, spans blend file loading */ #endif bgl::InitExtensions(true); // VBO code for derived mesh is not compatible with BGE (couldn't find why), so disable int disableVBO = (U.gameflags & USER_DISABLE_VBO); U.gameflags |= USER_DISABLE_VBO; // Globals to be carried on over blender files GlobalSettings gs; gs.matmode= startscene->gm.matmode; gs.glslflag= startscene->gm.flag; do { View3D *v3d= CTX_wm_view3d(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); // get some preferences SYS_SystemHandle syshandle = SYS_GetSystem(); bool properties = (SYS_GetCommandLineInt(syshandle, "show_properties", 0) != 0); bool usefixed = (SYS_GetCommandLineInt(syshandle, "fixedtime", 0) != 0); bool profile = (SYS_GetCommandLineInt(syshandle, "show_profile", 0) != 0); bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool animation_record = (SYS_GetCommandLineInt(syshandle, "animation_record", 0) != 0); bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0); #ifdef WITH_PYTHON bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); #endif // bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0); bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE; bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES; if (animation_record) usefixed= false; /* override since you don't want to run full-speed for sim recording */ // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(wm, win, area_rect, ar); // default mouse state set on render panel if (mouse_state) canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); else canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); RAS_IRenderTools* rendertools = new KX_BlenderRenderTools(); RAS_IRasterizer* rasterizer = NULL; //Don't use displaylists with VBOs //If auto starts using VBOs, make sure to check for that here if (displaylists && startscene->gm.raster_storage != RAS_STORE_VBO) rasterizer = new RAS_ListRasterizer(canvas, true, startscene->gm.raster_storage); else rasterizer = new RAS_OpenGLRasterizer(canvas, startscene->gm.raster_storage); RAS_IRasterizer::MipmapOption mipmapval = rasterizer->GetMipmapping(); // create the inputdevices KX_BlenderKeyboardDevice* keyboarddevice = new KX_BlenderKeyboardDevice(); KX_BlenderMouseDevice* mousedevice = new KX_BlenderMouseDevice(); // create a networkdevice NG_NetworkDeviceInterface* networkdevice = new NG_LoopBackNetworkDeviceInterface(); // // create a ketsji/blendersystem (only needed for timing and stuff) KX_BlenderSystem* kxsystem = new KX_BlenderSystem(); // create the ketsjiengine KX_KetsjiEngine* ketsjiengine = new KX_KetsjiEngine(kxsystem); // set the devices ketsjiengine->SetKeyboardDevice(keyboarddevice); ketsjiengine->SetMouseDevice(mousedevice); ketsjiengine->SetNetworkDevice(networkdevice); ketsjiengine->SetCanvas(canvas); ketsjiengine->SetRenderTools(rendertools); ketsjiengine->SetRasterizer(rasterizer); ketsjiengine->SetUseFixedTime(usefixed); ketsjiengine->SetTimingDisplay(frameRate, profile, properties); ketsjiengine->SetRestrictAnimationFPS(restrictAnimFPS); KX_KetsjiEngine::SetExitKey(ConvertKeyCode(startscene->gm.exitkey)); //set the global settings (carried over if restart/load new files) ketsjiengine->SetGlobalSettings(&gs); #ifdef WITH_PYTHON CValue::SetDeprecationWarnings(nodepwarnings); #endif //lock frame and camera enabled - storing global values int tmp_lay= startscene->lay; Object *tmp_camera = startscene->camera; if (v3d->scenelock==0) { startscene->lay= v3d->lay; startscene->camera= v3d->camera; } // some blender stuff float camzoom; int draw_letterbox = 0; if (rv3d->persp==RV3D_CAMOB) { if (startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) { /* Letterbox */ camzoom = 1.0f; draw_letterbox = 1; } else { camzoom = 1.0f / BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); } } else { camzoom = 2.0; } ketsjiengine->SetDrawType(v3d->drawtype); ketsjiengine->SetCameraZoom(camzoom); // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file if (exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME || exitrequested == KX_EXIT_REQUEST_RESTART_GAME) { exitrequested = KX_EXIT_REQUEST_NO_REQUEST; if (bfd) BLO_blendfiledata_free(bfd); char basedpath[FILE_MAX]; // base the actuator filename with respect // to the original file working directory if (exitstring != "") strcpy(basedpath, exitstring.Ptr()); // load relative to the last loaded file, this used to be relative // to the first file but that makes no sense, relative paths in // blend files should be relative to that file, not some other file // that happened to be loaded first BLI_path_abs(basedpath, pathname); bfd = load_game_data(basedpath); // if it wasn't loaded, try it forced relative if (!bfd) { // just add "//" in front of it char temppath[242]; strcpy(temppath, "//"); strcat(temppath, basedpath); BLI_path_abs(temppath, pathname); bfd = load_game_data(temppath); } // if we got a loaded blendfile, proceed if (bfd) { blenderdata = bfd->main; startscenename = bfd->curscene->id.name + 2; if (blenderdata) { BLI_strncpy(G.main->name, blenderdata->name, sizeof(G.main->name)); BLI_strncpy(pathname, blenderdata->name, sizeof(pathname)); #ifdef WITH_PYTHON setGamePythonPath(G.main->name); #endif } } // else forget it, we can't find it else { exitrequested = KX_EXIT_REQUEST_QUIT_GAME; } } Scene *scene= bfd ? bfd->curscene : (Scene *)BLI_findstring(&blenderdata->scene, startscenename, offsetof(ID, name) + 2); if (scene) { int startFrame = scene->r.cfra; ketsjiengine->SetAnimRecordMode(animation_record, startFrame); // Quad buffered needs a special window. if (scene->gm.stereoflag == STEREO_ENABLED) { if (scene->gm.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) scene->gm.stereomode); rasterizer->SetEyeSeparation(scene->gm.eyeseparation); } rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f); } if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME) { if (rv3d->persp != RV3D_CAMOB) { ketsjiengine->EnableCameraOverride(startscenename); ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == RV3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(MT_CmMatrix4x4(rv3d->winmat)); ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat)); if (rv3d->persp == RV3D_ORTHO) { ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } else { ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } ketsjiengine->SetCameraOverrideLens(v3d->lens); } // create a scene converter, create and convert the startingscene KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine); ketsjiengine->SetSceneConverter(sceneconverter); sceneconverter->addInitFromFrame=false; if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); bool usemat = false, useglslmat = false; if (GLEW_ARB_multitexture && GLEW_VERSION_1_1) usemat = true; if (GPU_glsl_support()) useglslmat = true; else if (gs.matmode == GAME_MAT_GLSL) usemat = false; if (usemat && (gs.matmode != GAME_MAT_TEXFACE)) sceneconverter->SetMaterials(true); if (useglslmat && (gs.matmode == GAME_MAT_GLSL)) sceneconverter->SetGLSLMaterials(true); if (scene->gm.flag & GAME_NO_MATERIAL_CACHING) sceneconverter->SetCacheMaterials(false); KX_Scene* startscene = new KX_Scene(keyboarddevice, mousedevice, networkdevice, startscenename, scene, canvas); #ifdef WITH_PYTHON // some python things PyObject *gameLogic, *gameLogic_keys; setupGamePython(ketsjiengine, startscene, blenderdata, pyGlobalDict, &gameLogic, &gameLogic_keys, 0, NULL); #endif // WITH_PYTHON //initialize Dome Settings if (scene->gm.stereoflag == STEREO_DOME) ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext); // initialize 3D Audio Settings AUD_I3DDevice* dev = AUD_get3DDevice(); if (dev) { dev->setSpeedOfSound(scene->audio.speed_of_sound); dev->setDopplerFactor(scene->audio.doppler_factor); dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model)); } // from see blender.c: // FIXME: this version patching should really be part of the file-reading code, // but we still get too many unrelated data-corruption crashes otherwise... if (blenderdata->versionfile < 250) do_versions_ipos_to_animato(blenderdata); if (sceneconverter) { // convert and add scene sceneconverter->ConvertScene( startscene, rendertools, canvas); ketsjiengine->AddScene(startscene); // init the rasterizer rasterizer->Init(); // start the engine ketsjiengine->StartEngine(true); // Set the animation playback rate for ipo's and actions // the framerate below should patch with FPS macro defined in blendef.h // Could be in StartEngine set the framerate, we need the scene to do this ketsjiengine->SetAnimFrameRate(FPS); #ifdef WITH_PYTHON char *python_main = NULL; pynextframestate.state = NULL; pynextframestate.func = NULL; python_main = KX_GetPythonMain(scene); // the mainloop printf("\nBlender Game Engine Started\n"); if (python_main) { char *python_code = KX_GetPythonCode(blenderdata, python_main); if (python_code) { ketsjinextframestate.ketsjiengine = ketsjiengine; ketsjinextframestate.C = C; ketsjinextframestate.win = win; ketsjinextframestate.scene = scene; ketsjinextframestate.ar = ar; ketsjinextframestate.keyboarddevice = keyboarddevice; ketsjinextframestate.mousedevice = mousedevice; ketsjinextframestate.draw_letterbox = draw_letterbox; pynextframestate.state = &ketsjinextframestate; pynextframestate.func = &BL_KetsjiPyNextFrame; printf("Yielding control to Python script '%s'...\n", python_main); PyRun_SimpleString(python_code); printf("Exit Python script '%s'\n", python_main); MEM_freeN(python_code); } } else #endif /* WITH_PYTHON */ { while (!exitrequested) { exitrequested = BL_KetsjiNextFrame(ketsjiengine, C, win, scene, ar, keyboarddevice, mousedevice, draw_letterbox); } } printf("Blender Game Engine Finished\n"); exitstring = ketsjiengine->GetExitString(); #ifdef WITH_PYTHON if (python_main) MEM_freeN(python_main); #endif /* WITH_PYTHON */ gs = *(ketsjiengine->GetGlobalSettings()); // when exiting the mainloop #ifdef WITH_PYTHON // Clears the dictionary by hand: // This prevents, extra references to global variables // inside the GameLogic dictionary when the python interpreter is finalized. // which allows the scene to safely delete them :) // see: (space.c)->start_game //PyDict_Clear(PyModule_GetDict(gameLogic)); // Keep original items, means python plugins will autocomplete members PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic)); const Py_ssize_t numitems= PyList_GET_SIZE(gameLogic_keys_new); Py_ssize_t listIndex; for (listIndex=0; listIndex < numitems; listIndex++) { PyObject *item = PyList_GET_ITEM(gameLogic_keys_new, listIndex); if (!PySequence_Contains(gameLogic_keys, item)) { PyDict_DelItem( PyModule_GetDict(gameLogic), item); } } Py_DECREF(gameLogic_keys_new); gameLogic_keys_new = NULL; #endif ketsjiengine->StopEngine(); #ifdef WITH_PYTHON exitGamePythonScripting(); #endif networkdevice->Disconnect(); } if (sceneconverter) { delete sceneconverter; sceneconverter = NULL; } #ifdef WITH_PYTHON Py_DECREF(gameLogic_keys); gameLogic_keys = NULL; #endif } //lock frame and camera enabled - restoring global values if (v3d->scenelock==0) { startscene->lay= tmp_lay; startscene->camera= tmp_camera; } if (exitrequested != KX_EXIT_REQUEST_OUTSIDE) { // set the cursor back to normal canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); // set mipmap setting back to its original value rasterizer->SetMipmapping(mipmapval); } // clean up some stuff if (ketsjiengine) { delete ketsjiengine; ketsjiengine = NULL; } if (kxsystem) { delete kxsystem; kxsystem = NULL; } if (networkdevice) { delete networkdevice; networkdevice = NULL; } if (keyboarddevice) { delete keyboarddevice; keyboarddevice = NULL; } if (mousedevice) { delete mousedevice; mousedevice = NULL; } if (rasterizer) { delete rasterizer; rasterizer = NULL; } if (rendertools) { delete rendertools; rendertools = NULL; } if (canvas) { delete canvas; canvas = NULL; } // stop all remaining playing sounds AUD_getDevice()->stopAll(); } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME); if (!disableVBO) U.gameflags &= ~USER_DISABLE_VBO; if (bfd) BLO_blendfiledata_free(bfd); BLI_strncpy(G.main->name, oldsce, sizeof(G.main->name)); #ifdef WITH_PYTHON Py_DECREF(pyGlobalDict); // Release Python's GIL PyGILState_Release(gilstate); #endif }
/****************************************************************************** * * Call the python object with all arguments * */ static void _CallPythonObject(void *mem, ffi_type *restype, SETFUNC setfunc, PyObject *callable, PyObject *converters, int flags, void **pArgs) { Py_ssize_t i; PyObject *result; PyObject *arglist = NULL; Py_ssize_t nArgs; PyObject *error_object = NULL; int *space; #ifdef WITH_THREAD PyGILState_STATE state = PyGILState_Ensure(); #endif nArgs = PySequence_Length(converters); /* Hm. What to return in case of error? For COM, 0xFFFFFFFF seems better than 0. */ if (nArgs < 0) { PrintError("BUG: PySequence_Length"); goto Done; } arglist = PyTuple_New(nArgs); if (!arglist) { PrintError("PyTuple_New()"); goto Done; } for (i = 0; i < nArgs; ++i) { /* Note: new reference! */ PyObject *cnv = PySequence_GetItem(converters, i); StgDictObject *dict; if (cnv) dict = PyType_stgdict(cnv); else { PrintError("Getting argument converter %d\n", i); goto Done; } if (dict && dict->getfunc && !_ctypes_simple_instance(cnv)) { PyObject *v = dict->getfunc(*pArgs, dict->size); if (!v) { PrintError("create argument %d:\n", i); Py_DECREF(cnv); goto Done; } PyTuple_SET_ITEM(arglist, i, v); /* XXX XXX XX We have the problem that c_byte or c_short have dict->size of 1 resp. 4, but these parameters are pushed as sizeof(int) bytes. BTW, the same problem occurs when they are pushed as parameters */ } else if (dict) { /* Hm, shouldn't we use PyCData_AtAddress() or something like that instead? */ CDataObject *obj = (CDataObject *)PyObject_CallFunctionObjArgs(cnv, NULL); if (!obj) { PrintError("create argument %d:\n", i); Py_DECREF(cnv); goto Done; } if (!CDataObject_Check(obj)) { Py_DECREF(obj); Py_DECREF(cnv); PrintError("unexpected result of create argument %d:\n", i); goto Done; } memcpy(obj->b_ptr, *pArgs, dict->size); PyTuple_SET_ITEM(arglist, i, (PyObject *)obj); #ifdef MS_WIN32 TryAddRef(dict, obj); #endif } else { PyErr_SetString(PyExc_TypeError, "cannot build parameter"); PrintError("Parsing argument %d\n", i); Py_DECREF(cnv); goto Done; } Py_DECREF(cnv); /* XXX error handling! */ pArgs++; } #define CHECK(what, x) \ if (x == NULL) _PyTraceback_Add(what, "_ctypes/callbacks.c", __LINE__ - 1), PyErr_Print() if (flags & (FUNCFLAG_USE_ERRNO | FUNCFLAG_USE_LASTERROR)) { error_object = _ctypes_get_errobj(&space); if (error_object == NULL) goto Done; if (flags & FUNCFLAG_USE_ERRNO) { int temp = space[0]; space[0] = errno; errno = temp; } #ifdef MS_WIN32 if (flags & FUNCFLAG_USE_LASTERROR) { int temp = space[1]; space[1] = GetLastError(); SetLastError(temp); } #endif } result = PyObject_CallObject(callable, arglist); CHECK("'calling callback function'", result); #ifdef MS_WIN32 if (flags & FUNCFLAG_USE_LASTERROR) { int temp = space[1]; space[1] = GetLastError(); SetLastError(temp); } #endif if (flags & FUNCFLAG_USE_ERRNO) { int temp = space[0]; space[0] = errno; errno = temp; } Py_XDECREF(error_object); if ((restype != &ffi_type_void) && result) { PyObject *keep; assert(setfunc); #ifdef WORDS_BIGENDIAN /* See the corresponding code in callproc.c, around line 961 */ if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg)) mem = (char *)mem + sizeof(ffi_arg) - restype->size; #endif keep = setfunc(mem, result, 0); CHECK("'converting callback result'", keep); /* keep is an object we have to keep alive so that the result stays valid. If there is no such object, the setfunc will have returned Py_None. If there is such an object, we have no choice than to keep it alive forever - but a refcount and/or memory leak will be the result. EXCEPT when restype is py_object - Python itself knows how to manage the refcount of these objects. */ if (keep == NULL) /* Could not convert callback result. */ PyErr_WriteUnraisable(callable); else if (keep == Py_None) /* Nothing to keep */ Py_DECREF(keep); else if (setfunc != _ctypes_get_fielddesc("O")->setfunc) { if (-1 == PyErr_WarnEx(PyExc_RuntimeWarning, "memory leak in callback function.", 1)) PyErr_WriteUnraisable(callable); } } Py_XDECREF(result); Done: Py_XDECREF(arglist); #ifdef WITH_THREAD PyGILState_Release(state); #endif }
static void gil_greenlet_release() { PyGILState_Release((PyGILState_STATE) pthread_getspecific(up.upt_gil_key)); }