per Voo's advice on this thread:
How can I "hook into" Python from C++ when it executes a function? My goal is to profile
I have opened up a new thread for a new question, which is, in C++, how can I initialize a PythonInterpreter and then call a method from it. Specifically, I'd like to be able to call cProfile's methods and also get data from it.
Okay that'll be a bit longer. Note that I pretty much ignore all "usual" error checking - pretty much any python method may return NULL in which case you should handle that gracefully. I show the "unusual" part checking if the given object is callable. Note that PyDECREF fails if the object pointer is NULL, Py_XDECREF does not. And now to the code - there may be a better way to solve all this, but this works fine for me and sadly the documentation is extremely lacking.
C++ code:
#include <Python.h>
static PyThreadState *mainstate;
void initPython(){
PyEval_InitThreads();
Py_Initialize();
mainstate = PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
}
void exitPython(){
PyEval_AcquireLock();
PyThreadState_Swap(mainstate);
Py_Finalize();
}
void callScript() {
PyGILState_STATE gstate = PyGILState_Ensure();
PyObject *pName = PyUnicode_FromString("Startup");
PyObject *pModule = PyImport_Import(pName);
Py_DECREF(pName);
PyObject *pFunc = PyObject_GetAttrString(pModule, "startup");
if (pFunc && PyCallable_Check(pFunc)) {
PyObject *arglist = Py_BuildValue("(u)", "TestScript");
PyObject *result = PyObject_CallObject(pFunc, arglist);
Py_DECREF(arglist);
// Now you have the returned object of the function - do something with it.
// In our case that's None, but you should extend the python scrip to return
// whatever you need - see the profiler API.
Py_DECREF(result);
}
Py_XDECREF(pFunc); // XDECREF does not fail if pointer is NULL.
Py_DECREF(pModule);
PyGILState_Release(gstate);
}
int main() {
printf("Start.\n");
initPython();
callScript();
exitPython();
printf("Exit.\n");
return 0;
}
Your specific script that is always called, change this so that you return all the data you want in a useful manner - at the moment we just use cProfile.run() which just prints some information:
Startup.py
import cProfile
def startup(module_name):
print("Start script")
cProfile.run("import " + module_name)
print("Finished script")
Finally the trivial script that is executed:
TestScript.py
sum = 0
for i in range(10000):
sum += i
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.