Fix T75889: Cannot bake mantaflow via Python API

The issue was the usage of the global `__main__` Python module.
When running scripts in the text editor, Blender would overwrite
the `__main__` module.

Reviewers: sebbas

Differential Revision: https://developer.blender.org/D7690
This commit is contained in:
Jacques Lucke 2020-05-12 12:12:21 +02:00
parent 2008bcb0bb
commit a50c131a0d

@ -538,19 +538,49 @@ MANTA::~MANTA()
(void)result; // not needed in release
}
/**
* Store a pointer to the __main__ module used by mantaflow. This is necessary, because sometimes
* Blender will overwrite that module. That happens when e.g. scripts are executed in the text
* editor.
*
* 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.
*
* 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.
*/
static PyObject *manta_main_module = nullptr;
bool MANTA::runPythonString(std::vector<std::string> commands)
{
int success = -1;
bool success = true;
PyGILState_STATE gilstate = PyGILState_Ensure();
if (manta_main_module == nullptr) {
manta_main_module = PyImport_ImportModule("__main__");
}
for (std::vector<std::string>::iterator it = commands.begin(); it != commands.end(); ++it) {
std::string command = *it;
success = PyRun_SimpleString(command.c_str());
PyObject *globals_dict = PyModule_GetDict(manta_main_module);
PyObject *return_value = PyRun_String(
command.c_str(), Py_file_input, globals_dict, globals_dict);
if (return_value == nullptr) {
success = false;
if (PyErr_Occurred()) {
PyErr_Print();
}
}
else {
Py_DECREF(return_value);
}
}
PyGILState_Release(gilstate);
/* PyRun_SimpleString returns 0 on success, -1 when an error occurred. */
assert(success == 0);
return (success != -1);
assert(success);
return success;
}
void MANTA::initializeMantaflow()
@ -2124,19 +2154,18 @@ static PyObject *callPythonFunction(std::string varName,
}
PyGILState_STATE gilstate = PyGILState_Ensure();
PyObject *main = nullptr, *var = nullptr, *func = nullptr, *returnedValue = nullptr;
PyObject *var = nullptr, *func = nullptr, *returnedValue = nullptr;
/* Be sure to initialise Python before importing main. */
/* Be sure to initialize Python before using it. */
Py_Initialize();
// Get pyobject that holds result value
main = PyImport_ImportModule("__main__");
if (!main) {
if (!manta_main_module) {
PyGILState_Release(gilstate);
return nullptr;
}
var = PyObject_GetAttrString(main, varName.c_str());
var = PyObject_GetAttrString(manta_main_module, varName.c_str());
if (!var) {
PyGILState_Release(gilstate);
return nullptr;