Hello!
I am trying to embed Python into my C++ application. After some simple testing I decided it would be good to have a PythonManager-class, so I wrote one.
class PythonManager {
public:
PythonManager(CNetwork *n);
~PythonManager();
void privRespond(const std::string &rcvr, const std::string &sndr, const std::string &hst, const std::string &msg);
private:
std::vector<PyObject *> prvFuncs;
CNetwork *net;
std::string out;
PyObject *pName;
PyObject *pModule;
PyObject *pDict;
PyObject *pFunc;
PyObject *pValue;
PyObject *pArgs;
};
In the destructor of this class, I call the Py_Finalize() function. The constructor is responsible for loading all the python-scripts and calling Py_Initialize(). The privRespond()-method will loop through all the registered python-scripts that contains the function "OnPrivMsg()" and pass on the arguments to all of them. This is what it looks like in my test script (base.py)
def OnPrivMsg(receiver, sender, host, message):
return "PRIVMSG "+receiver+" :Hello "+sender+"!"
This works like a charm. However, when I call Py_Finalize() in the destructor I get an access violation and my app crashes. It is because of something I do wrong in the privRespond-method, because if I comment it out I don't get the access violation.
This is what the method looks like:
void PythonManager::privRespond(const std::string &rcvr, const std::string &sndr, const std::string &hst, const std::string &msg) {
for ( int i=0; i<prvFuncs.size(); i++ ) {
pArgs = PyTuple_New(4);
pValue = PyString_FromString(rcvr.c_str());
PyTuple_SetItem(pArgs, 0, pValue);
pValue = PyString_FromString(sndr.c_str());
PyTuple_SetItem(pArgs, 1, pValue);
pValue = PyString_FromString(hst.c_str());
PyTuple_SetItem(pArgs, 2, pValue);
pValue = PyString_FromString(msg.c_str());
PyTuple_SetItem(pArgs, 3, pValue);
pValue = PyObject_CallObject(prvFuncs, pArgs);
Py_DECREF(pArgs);
out = PyString_AsString(pValue);
Py_DECREF(pValue);
out += "\r\n";
net->Send(out);
}
}
Now, my guess is it has something to do with reference counts, but I don't get it, even after reading every article I could find using google.
I will post the destructor code also:
PythonManager::~PythonManager() {
// Clean up
Py_DECREF(pModule);
// Shutdown the python interpreter
Py_Finalize();
}
Thanks in advance!