[C++-sig] Object lifetime issue

Matt Holmes tegan at gnometank.net
Sun Sep 2 01:07:47 CEST 2007


I am trying to expose one of the classes in my engine as an abstract 
class that is used as the base for a series of Python classes.

That class is called InputCommand and is defined as such:
namespace Stasis {
	class InputCommand {
	public:
		virtual bool execute() = 0;
	};
}

To expose that class, I created the following wrapper:

class InputCommandWrapper : public Stasis::InputCommand, public 
wrapper<Stasis::InputCommand> {
public:
	bool execute() {
		return this->get_override("execute")();
	}
};

And added it to my Boost.Python module like so:

class_<InputCommandWrapper, boost::noncopyable>("InputCommand")
	.def("execute", pure_virtual(&InputCommand::execute));

Everything seems okay so far, but then I have another class called 
InputManager. This class exposes a function, registerCommand, that takes 
a const std::string& and an InputCommand*. That classes partial 
defintion is:

class InputManager : public Singleton<InputManager>
public:
	static InputManager& getSingleton() { return *ms_Singleton; }
	static InputManager* getSingletonPtr() { return ms_Singleton; }

	InputManager();
	~InputManager();
		
	void executeCommand(const string& cmdName);
	void registerCommand(const string& cmdName, InputCommand* cmd);
}

It is defined in the Boost.Python module as such:

class_<InputManager>("InputManager")
	.def("registerCommand", &InputManager::registerCommand, 
with_custodian_and_ward_postcall<1, 3>())
	.def("getSingleton", &InputManager::getSingleton, 
return_value_policy<reference_existing_object>()).staticmethod("getSingleton");

I am executing the follwing Python script, which should create an 
instance of the QuitCommand object, pass it to the 
InputManagers::registerCommand method, which will store that command 
object and use it to execute the given command later (which is 
implemented in Python). The issue is that when I call the execute() 
method of my store InputCommand*, my program crashes. From what I can 
tell it's because Python is destroying the object I created in the 
Python script below to pass to registerCommand. I thought 
with_custodian_and_ward<1, 3> (the custodian should be 'this', the 
InputManader, and the ward should be the InputCommand sub-class object) 
would stop the Python GC from destroying it, but I guess I was wrong.

Here is the Python script:

from engine import *

class QuitCommand(InputCommand):
     def execute(self):
         Kernel.getSingleton().shutdown()

if __name__ == "__main__":
     InputManager.getSingleton().registerCommand("Quit", QuitCommand())

What am I doing wrong here? What do I need to do to tell Python "The 
QuitCommand() object I just created, don't destroy it, something else is 
holding a reference to it"?




More information about the Cplusplus-sig mailing list