Embedding Python into a C++application

Started by
2 comments, last by Pepper_ 18 years, 6 months ago
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!
Advertisement
I don't see anything immediately wrong with your code (which admittedly doesn't mean much). Have considered using boost::python to manage your reference counts instead?
Yeah I looked at it briefly, but decided to try without it. Anyway, I think I'm gonna use it now anyway, since I ran into this much trouble. I just thought I'd ask here first.

Anyway, thanks for your reply!

Regards,
Anton
I have a new problem. This python code works:
count = 4def OnJoin(receiver, sender, host, message):	return "PRIVMSG "+receiver+" :Joincount is "+str(count)+" (base.py)"

And this
count = 4def OnJoin(receiver, sender, host, message):	count = 7 # NEW	return "PRIVMSG "+receiver+" :Joincount is "+str(count)+" (base.py)"

However, this doesn't:
count = 4def OnJoin(receiver, sender, host, message):	count += 1 # NEW	return "PRIVMSG "+receiver+" :Joincount is "+str(count)+" (base.py)"

Why doesn't that work? When in the python console or in "IDLE" it works... The host c++ app stalls and crashes when this python function is called.

Edit:
I'm done with python now... I think it sucks. I will instead use the mighty language of Pawn (http://www.compuphase.com/pawn/pawn.htm) You should try it too!

[Edited by - Pepper_ on October 8, 2005 9:28:00 PM]

This topic is closed to new replies.

Advertisement