[C++-sig] Boost::python and shared_ptr
Bernhard Glück
bernhardprivat at realspace.org
Tue Jan 4 21:45:10 CET 2005
Hi !
I am using a boost::python to script our newest project.
We use boost::shared_ptr for almost all of our objects.
How do i correctly wrap my classes so that they are held as shared_ptr
objects and
passed around that way ? I tried doing it like it was posted this
mailing list
before, but with the following problems.
My environment is as follows::
Python 2.4,
Boost 1.32.0
Compiler: VC7.1
Here the relevant code passages:
First our game object which holds smart pointers to several sub systems:
typedef boost::shared_ptr< class GraphicsServer > GraphicsServerPtr;
typedef boost::shared_ptr< class AudioServer >
AudioServerPtr;
typedef boost::shared_ptr< class ScriptServer >
ScriptServerPtr;
typedef boost::shared_ptr< class InputServer >
InputServerPtr;
typedef boost::shared_ptr< class PhysicsServer >
PhysicsServerPtr;
typedef boost::shared_ptr< class AiServer > AiServerPtr;
typedef boost::shared_ptr< class ConfigurationServer >
ConfigurationServerPtr;
typedef boost::shared_ptr< class TimeServer > TimeServerPtr;
class Game : public Ogre::Singleton<Game>,
public Ogre::FrameListener
{
public:
const GraphicsServerPtr & GetGraphicsServer() const;
const AudioServerPtr & GetAudioServer() const;
const ScriptServerPtr & GetScriptServer() const;
const InputServerPtr & GetInputServer() const;
const PhysicsServerPtr & GetPhysicsServer() const;
const AiServerPtr & GetAiServer() const;
const ConfigurationServerPtr & GetConfigurationServer() const;
const TimeServerPtr & GetTimeServer() const;
void Start();
void Stop();
bool frameStarted(const Ogre::FrameEvent& evt);
bool frameEnded( const Ogre::FrameEvent & evt);
Game();
virtual ~Game();
private:
GraphicsServerPtr mGraphicsServer;
AudioServerPtr mAudioServer;
ScriptServerPtr mScriptServer;
InputServerPtr mInputServer;
PhysicsServerPtr mPhysicsServer;
AiServerPtr mAiServer;
ConfigurationServerPtr mConfigurationServer;
TimeServerPtr mTimeServer;
bool mStop;
};
Now our configuration server code that stores "registry" style values (
configuration information for our game )
class ConfigurationServer : public Server
{
public:
template<typename T>
inline T GetValue( const std::string & name,T defaultValue )
{
if ( mValues.find(name) != mValues.end() )
{
boost::any value = mValues[name];
if ( value.type() == typeid(T ))
{
return boost::any_cast<T>(value);
}
else
{
boost::format errorFmt("Configuration value
(%1%) of wrong type (%2%),
expected (%3%), using default of (%4%).");
errorFmt % name;
errorFmt % value.type().name();
errorFmt % typeid(T).name();
errorFmt % defaultValue;
Log( errorFmt.str() );
}
}
else
{
boost::format errorFmt("Configuration value
(%1%) not found, using default of (%2%).");
errorFmt % name;
errorFmt % defaultValue;
Log( errorFmt.str() );
}
return defaultValue;
}
template<typename T>
inline void SetValue( const std::string & name,T value )
{
mValues[name] = boost::any(value);
}
virtual bool Reset();
virtual bool Initialize();
virtual bool Shutdown();
virtual bool Update( float deltaTime );
ConfigurationServer();
virtual ~ConfigurationServer();
private:
std::map<std::string,boost::any> mValues;
};
And now the export part:
///////////////////////////////////////////////////////////
void PyExportConfigurationServer()
{
Log("Exported configuration server.");
void (ConfigurationServer::*cm1)( const std::string &,int )
=
&ConfigurationServer::SetValue;
void (ConfigurationServer::*cm2)( const std::string
&,float)=&ConfigurationServer::SetValue;
void (ConfigurationServer::*cm3)( const std::string &,bool )
=&ConfigurationServer::SetValue;
void (ConfigurationServer::*cm4)( const std::string &,std::string )
=&ConfigurationServer::SetValue;
register_ptr_to_python< boost::shared_ptr<ConfigurationServer> >();
class_< ConfigurationServer,boost::shared_ptr<ConfigurationServer> >
("ConfigurationServer",no_init )
.def("set",cm1)
.def("set",cm2)
.def("set",cm3)
.def("set",cm4);
}
///////////////////////////////////////////////////////////
void PyExportGame()
{
DeepVoid::Log("Exported game.");
class_<Game> ("Game",no_init )
.def("quit",&Game::Stop )
.def("getConfigurationServer",&Game::GetConfigurationServer,
return_value_policy<reference_existing_object>());
def("getGame",&Game::getSingleton,
return_value_policy<reference_existing_object>());
}
///////////////////////////////////////////////////////////
BOOST_PYTHON_MODULE(dv)
{
PyExportConfigurationServer();
PyExportGame();
}
The problem now is that the game class works as expected but whenever i do
something like this:
import dv
game = dv.getGame()
config = game.getConfigurationServer()
config.set("Graphics.Fullscreen",1)
I get the following error:
exceptions.TypeError
20:54:20: No Python class registered for C++ class class
boost::shared_ptr<class
DeepVoid::ConfigurationServer>
20:54:20: File "DeepVoidConfig.py", line 3, in ? config =
game.getConfigurationServer()
I have no clue why this could happen. I tried chaning the export code
for the
ConfiguratioNServer in various ways ( leaving out register_ptr_to_python,
or the second wrapper definition ) to no avail..
Both classes get exported by the way ( as my log tells me, thats why i have
those two Log statements in the code )....
So what can i do to pass around my objects as shared_ptrs ?
Ideally i would like almost all objects of our engine to be held in
shared_ptr instead of normal ones.
Hope anyone can help :-)
Thanks in advance
Bernhard Glück
More information about the Cplusplus-sig
mailing list