bool EventListener::Compile() { Rocket::Core::String function_name(64, "Event_%x", this); Rocket::Core::String function_code(64, "def %s():", function_name.CString()); Rocket::Core::StringList lines; Rocket::Core::StringUtilities::ExpandString(lines, source_code, ';'); for (size_t i = 0; i < lines.size(); i++) { // Python doesn't handle \r's, strip em and indent the code correctly function_code += Rocket::Core::String(1024, "\n\t%s", lines[i].CString()).Replace("\r", ""); } ROCKET_ASSERT(element != NULL); PyObject* py_namespace = GetGlobalNamespace(); // Add our function to the namespace PyObject* result = PyRun_String(function_code.CString(), Py_file_input, py_namespace, py_namespace); if (!result) { Rocket::Core::Python::Utilities::PrintError(); return false; } Py_DECREF(result); // Get a handle to our function callable = PyDict_GetItemString(py_namespace, function_name.CString()); Py_INCREF(callable); return true; }
void EventListener::ProcessEvent(Event& event) { // If we've got nothing to do, abort if (!callable && source_code.Empty()) return; // Do we need to compile the code? if (!callable && !source_code.Empty()) { // Attempt to compile the code if (!Compile()) return; } PyObject* py_namespace = GetGlobalNamespace(); // Store current globals PyObject* old_event = PyDict_GetItemString(py_namespace, "event"); PyObject* old_self = PyDict_GetItemString(py_namespace, "self"); PyObject* old_document = PyDict_GetItemString(py_namespace, "document"); // Clear any pending errors (KeyErrors if they didn't exist) PyErr_Clear(); // Increase the ref to store the old values locally Py_XINCREF(old_event); Py_XINCREF(old_self); Py_XINCREF(old_document); // Set up the new expected globals PyDict_SetItemString(py_namespace, "event", Rocket::Core::Python::Utilities::MakeObject(&event).ptr()); PyDict_SetItemString(py_namespace, "self", Rocket::Core::Python::Utilities::MakeObject(element).ptr()); // Call the bound function PyObject* result = NULL; try { result = PyObject_CallObject(callable, NULL); } catch (python::error_already_set&) { } // Check error conditions if (result) { Py_DECREF(result); } else { Rocket::Core::Python::Utilities::PrintError(true); } // Remove the globals PyDict_DelItemString(py_namespace, "document"); PyDict_DelItemString(py_namespace, "self"); PyDict_DelItemString(py_namespace, "event"); // Restore old events if necessary if (old_event) { PyDict_SetItemString(py_namespace, "event", old_event); Py_DECREF(old_event); } if (old_self) { PyDict_SetItemString(py_namespace, "self", old_self); Py_DECREF(old_self); } if (old_document) { PyDict_SetItemString(py_namespace, "document", old_document); Py_DECREF(old_document); } }