The API changed, in 3.x the function PyEval_EvalCode() takes a PyObject* instead of a PyCodeObject*. Probably because someone decided that maybe code objects aren't the only type of object that can be evaluated? Who knows. Py_CompileString() will return a PyCodeObject* so you're safe to cast it.
I was able to solve it with some help from the #python IRC channel: Apparently, passing the "globals" dict from the __main__ module to PyEval_EvalCode() will cause whatever functions are in the code object to be registered globally to the __main__ module, but will still be unavailable to the local module. The documentation is extremely sparse and I have to admit I don't understand why the following code works. What exactly happens with "globals" and "locals" in the call to PyEval_EvalCode(compiled, globals, locals)?
Anyway, here's the code that works:
void ScriptInstance::reload()
{ /*
* Need to clear everything that is currently in the module's dictionary,
* so it's not possible to accidentally call old functions that no longer
* exist.
*
* In order for the builtin functions to be defined, copy the __main__
* module's dictionary into the new module's local dictionary
*/
PyObject* locals = PyModule_GetDict(module_);
PyObject* main = PyImport_AddModule("__main__");
PyObject* globals = PyModule_GetDict(main);
PyDict_Clear(locals);
PyModule_AddStringConstant(module_, "__file__", "");
PyDict_Merge(locals, globals, 0);
/*
* Evaluate the code into this module's local dictionary.
*/
PythonObject<> eval = PyEval_EvalCode(compiled.get(), locals, locals);
flushFunction_ = PyObject_GetAttrString(module_, "flush");
}
Explanation:
Upon reloading, I have to clear the module's local dictionary of all items, to make sure it's impossible to call functions that are no longer defined in the script.
This isn't enough, because now the dictionary is empty, which means any scripts that are evaluated using this dictionary won't have access to any built-in commands like "print()" or "import". To fix this, I get the dictionary from __main__ (which defines all of these things) and merge it with the local dictionary.
Once that's done, I pass "local" twice to PyEval_EvalCode(). That fixes it.
Like I said: I don't fully understand why this works and would appreciate some explanation.
"I would try to find halo source code by bungie best fps engine ever created, u see why call of duty loses speed due to its detail." -- GettingNifty