Changeset View
Changeset View
Standalone View
Standalone View
intern/mantaflow/intern/MANTA_main.cpp
| Show First 20 Lines • Show All 561 Lines • ▼ Show 20 Lines | MANTA::~MANTA() | ||||
| pythonCommands.push_back(finalString); | pythonCommands.push_back(finalString); | ||||
| result = runPythonString(pythonCommands); | result = runPythonString(pythonCommands); | ||||
| BLI_assert(result); | BLI_assert(result); | ||||
| UNUSED_VARS(result); | UNUSED_VARS(result); | ||||
| } | } | ||||
| /** | /** | ||||
| * Store a pointer to the __main__ module used by mantaflow. This is necessary, because sometimes | * Copied from `PyC_DefaultNameSpace` in Blender. | ||||
| * Blender will overwrite that module. That happens when e.g. scripts are executed in the text | * with some differences: | ||||
| * editor. | * - Doesn't touch `sys.modules`, use #manta_python_main_module_activate instead. | ||||
| * | * - Returns the module instead of the modules `dict`. | ||||
| * */ | |||||
| static PyObject *manta_python_main_module_create(const char *filename) | |||||
| { | |||||
| PyObject *builtins = PyEval_GetBuiltins(); | |||||
| PyObject *mod_main = PyModule_New("__main__"); | |||||
| PyModule_AddStringConstant(mod_main, "__name__", "__main__"); | |||||
| if (filename) { | |||||
| /* __file__ mainly for nice UI'ness | |||||
| * NOTE: this won't map to a real file when executing text-blocks and buttons. */ | |||||
| PyModule_AddObject(mod_main, "__file__", PyUnicode_InternFromString(filename)); | |||||
| } | |||||
| PyModule_AddObject(mod_main, "__builtins__", builtins); | |||||
| Py_INCREF(builtins); /* AddObject steals a reference */ | |||||
| return mod_main; | |||||
| } | |||||
| static void manta_python_main_module_activate(PyObject *mod_main) | |||||
| { | |||||
| PyObject *modules = PyImport_GetModuleDict(); | |||||
| PyObject *main_mod_cmp = PyDict_GetItemString(modules, "__main__"); | |||||
| if (mod_main == main_mod_cmp) { | |||||
| return; | |||||
| } | |||||
| /* NOTE: we could remove the reference to `mod_main` here, but as it's know to be removed | |||||
| * accept that there is temporarily an extra reference. */ | |||||
| PyDict_SetItemString(modules, "__main__", mod_main); | |||||
| } | |||||
| static void manta_python_main_module_backup(PyObject **r_main_mod) | |||||
| { | |||||
| PyObject *modules = PyImport_GetModuleDict(); | |||||
| *r_main_mod = PyDict_GetItemString(modules, "__main__"); | |||||
| Py_XINCREF(*r_main_mod); /* don't free */ | |||||
| } | |||||
| static void manta_python_main_module_restore(PyObject *main_mod) | |||||
| { | |||||
| PyObject *modules = PyImport_GetModuleDict(); | |||||
| PyDict_SetItemString(modules, "__main__", main_mod); | |||||
| Py_XDECREF(main_mod); | |||||
| } | |||||
| /** | |||||
| * Mantaflow stores many variables in the globals() dict of the __main__ module. To be able to | * Mantaflow stores many variables in the globals() dict of the __main__ module. To be able to | ||||
| * access these variables, the same __main__ module has to be used every time. | * access these variables, the same __main__ module has to be used every time. | ||||
| * | * | ||||
| * Unfortunately, we also depend on the fact that mantaflow dumps variables into this module using | * Unfortunately, we also depend on the fact that mantaflow dumps variables into this module using | ||||
| * PyRun_SimpleString. So we can't easily create a separate module without changing mantaflow. | * PyRun_SimpleString. So we can't easily create a separate module without changing mantaflow. | ||||
| */ | */ | ||||
| static PyObject *manta_main_module = nullptr; | static PyObject *manta_main_module = nullptr; | ||||
| static void manta_python_main_module_clear() | |||||
| { | |||||
| if (manta_main_module) { | |||||
| Py_DECREF(manta_main_module); | |||||
| manta_main_module = nullptr; | |||||
| } | |||||
| } | |||||
| static PyObject *manta_python_main_module_ensure() | |||||
| { | |||||
| if (!manta_main_module) { | |||||
| manta_main_module = manta_python_main_module_create("<manta_namespace>"); | |||||
| } | |||||
| return manta_main_module; | |||||
| } | |||||
| bool MANTA::runPythonString(vector<string> commands) | bool MANTA::runPythonString(vector<string> commands) | ||||
| { | { | ||||
| bool success = true; | bool success = true; | ||||
| PyGILState_STATE gilstate = PyGILState_Ensure(); | PyGILState_STATE gilstate = PyGILState_Ensure(); | ||||
| /* Temporarily set `sys.modules["__main__"]` as some Python modules expect this. */ | |||||
| PyObject *main_mod_backup; | |||||
| manta_python_main_module_backup(&main_mod_backup); | |||||
| if (manta_main_module == nullptr) { | if (manta_main_module == nullptr) { | ||||
SonnyCampbell_Unity: Probably don't need a null check here and also in `manta_python_main_module_ensure` | |||||
| manta_main_module = PyImport_ImportModule("__main__"); | manta_main_module = manta_python_main_module_ensure(); | ||||
| } | } | ||||
| manta_python_main_module_activate(manta_main_module); | |||||
| for (vector<string>::iterator it = commands.begin(); it != commands.end(); ++it) { | for (vector<string>::iterator it = commands.begin(); it != commands.end(); ++it) { | ||||
| string command = *it; | string command = *it; | ||||
| PyObject *globals_dict = PyModule_GetDict(manta_main_module); | PyObject *globals_dict = PyModule_GetDict(manta_main_module); | ||||
| PyObject *return_value = PyRun_String( | PyObject *return_value = PyRun_String( | ||||
| command.c_str(), Py_file_input, globals_dict, globals_dict); | command.c_str(), Py_file_input, globals_dict, globals_dict); | ||||
| if (return_value == nullptr) { | if (return_value == nullptr) { | ||||
| success = false; | success = false; | ||||
| if (PyErr_Occurred()) { | if (PyErr_Occurred()) { | ||||
| PyErr_Print(); | PyErr_Print(); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| Py_DECREF(return_value); | Py_DECREF(return_value); | ||||
| } | } | ||||
| } | } | ||||
| manta_python_main_module_restore(main_mod_backup); | |||||
| PyGILState_Release(gilstate); | PyGILState_Release(gilstate); | ||||
| BLI_assert(success); | BLI_assert(success); | ||||
| return success; | return success; | ||||
| } | } | ||||
| void MANTA::initializeMantaflow() | void MANTA::initializeMantaflow() | ||||
| { | { | ||||
| if (with_debug) | if (with_debug) | ||||
| cout << "Fluid: Initializing Mantaflow framework" << endl; | cout << "Fluid: Initializing Mantaflow framework" << endl; | ||||
| string filename = "manta_scene_" + to_string(mCurrentID) + ".py"; | string filename = "manta_scene_" + to_string(mCurrentID) + ".py"; | ||||
| vector<string> fill = vector<string>(); | vector<string> fill = vector<string>(); | ||||
| /* Initialize extension classes and wrappers. */ | /* Initialize extension classes and wrappers. */ | ||||
| srand(0); | srand(0); | ||||
| PyGILState_STATE gilstate = PyGILState_Ensure(); | PyGILState_STATE gilstate = PyGILState_Ensure(); | ||||
| Pb::setup(filename, fill); /* Namespace from Mantaflow (registry). */ | |||||
| PyObject *manta_main_module = manta_python_main_module_ensure(); | |||||
| PyObject *globals_dict = PyModule_GetDict(manta_main_module); | |||||
| Pb::setup(filename, fill, globals_dict); /* Namespace from Mantaflow (registry). */ | |||||
| PyGILState_Release(gilstate); | PyGILState_Release(gilstate); | ||||
| } | } | ||||
| void MANTA::terminateMantaflow() | void MANTA::terminateMantaflow() | ||||
| { | { | ||||
| if (with_debug) | if (with_debug) | ||||
| cout << "Fluid: Releasing Mantaflow framework" << endl; | cout << "Fluid: Releasing Mantaflow framework" << endl; | ||||
| PyGILState_STATE gilstate = PyGILState_Ensure(); | PyGILState_STATE gilstate = PyGILState_Ensure(); | ||||
| Pb::finalize(); /* Namespace from Mantaflow (registry). */ | Pb::finalize(); /* Namespace from Mantaflow (registry). */ | ||||
| manta_python_main_module_clear(); | |||||
SonnyCampbell_UnityUnsubmitted Done Inline ActionsFrom checking the source code I couldn't actually find terminateMantaflow() being called anywhere, I put the clearing functionality in the destructor but should probably call terminateMantaflow() there SonnyCampbell_Unity: From checking the source code I couldn't actually find `terminateMantaflow()` being called… | |||||
| PyGILState_Release(gilstate); | PyGILState_Release(gilstate); | ||||
| } | } | ||||
| static string getCacheFileEnding(char cache_format) | static string getCacheFileEnding(char cache_format) | ||||
| { | { | ||||
| if (MANTA::with_debug) | if (MANTA::with_debug) | ||||
| cout << "MANTA::getCacheFileEnding()" << endl; | cout << "MANTA::getCacheFileEnding()" << endl; | ||||
| ▲ Show 20 Lines • Show All 1,619 Lines • Show Last 20 Lines | |||||
Probably don't need a null check here and also in manta_python_main_module_ensure