[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