// Non singleton
class MyLogManager
{
void write(message) {Ogre::LogManager::getSingletonPtr()->logMessage(message);}
}
class Utils : public singleton<Utils>
{
MyLogManager *handle;
MyLogManager& getHandle { return *handle; }
};
namespace someNamespace
{
MyLogManager &Log() { return Utils::get_mutable_instance().getHandle(); }
}
int main()
{
someNamespace::Log().write("Starting game initializating...");
}
In this code I'm using boost's singleton (from serialization) and calling Ogre's log manager (it's singleton-type too).
The program fails at any trying to do something with Ogre::LogManager::getSingletonPtr() object with code
User program stopped by signal (SIGSEGV)
I checked that getSingletonPtr() returns address 0x000
But using code Utils::get_mutable_instance().getHandle().write("foo") works good in another part of program. What's wrong could be there with calling singletons?
Real version of Utils class:
class Utils : public singleton<Utils>
{
protected:
ConfigManager *configHandlePtr;
LogManager *logHandlePtr;
public:
Utils()
{
configHandlePtr = new ConfigManager();
string engineLog = configHandle().getValue<string>("engine.logFilename", "Engine.log");
logHandlePtr = new LogManager(engineLog);
}
~Utils()
{
delete configHandlePtr;
delete logHandlePtr;
}
ConfigManager &configHandle() const { return *configHandlePtr; }
LogManager &logHandle() const { return *logHandlePtr; }
};
And here is the real code of LogManager class:
class LogManager
{
protected:
string mDefaultPath;
public:
LogManager(const string &logPath = "Engine.log") :
mDefaultPath(logPath) { }
void write(const string &message, const string logFile = "")
{
string workPath = mDefaultPath;
Ogre::LogManager *logHandle = Ogre::LogManager::getSingletonPtr(); // [logHandle=0x000]
Ogre::Log *log2Handle = logHandle->getLog(workPath); // [SEGFAULT]
log2Handle->logMessage(message);
Ogre::LogManager::getSingletonPtr()->logMessage(message);
}
};
UPDATE:
I have a static library (there is my engine code) and the main own programm which links static this library. When I call my config handle (which doesn't use Ogre) everything is okay! There is also resourceManager, it uses Ogre too. And it fails like logManager. Both this managers uses Ogre's singleton. Maybe it's impossible to call it from another library?
It feels like you have typical "static initialization order fiasco" - your Utils instance created before one (or both) of other singletons.
Try change Utils::configHandle() to something like this:
ConfigManager &configHandle() const {
static std::auto_ptr<ConfigManager> configHandlePtr(0);
if (!configHandlePtr.get()) {
configHandlePtr.reset(new ConfigManager());
// init configHandlePtr like you want
}
return *configHandlePtr;
}
I don't know Boost's singleton, but I notice some strange things in your 'Utils' class.
First of all, getHandle returns a reference to handle, but handle is a local variable that goes out of scope if you leave the method, so the reference to it will also be invalid.
Second, you didn't initialize handle in the getHandle method.
Are you sure your Ogre LogManager is correctly initialized?
Or maybe with your libraries you have one instance of the singleton in each library and only the one in your main program is correctly initialized?
In this case you have to declare the singletons in your libraries as "extern" but I'm not sure it applies to statically linked libraries.
Related
Suppose I have a program like this:
File main.cpp
#include "something.hpp"
int main(int argc, char* argv[]) {
some = new Something();
return 0;
}
which will be linked to a .so library consisting of following files:
File logger.hpp
#include <iostream>
class Logger {
public:
Logger();
void log(char);
void set_name(char);
private:
char m_name;
};
File logger.cpp
#include "logger.hpp"
Logger::Logger() {}
void Logger::log(char msg) {
std::cout << this->m_name << " : " << msg;
}
void Logger::set_name(char name) {
this->m_name = name;
}
File something.hpp
#include "logger.hpp"
class Something {
public:
Something();
};
File something.cpp
#include "something.hpp"
Something::Something() {
logger->log("hello !");
}
The code as it is now will fail in something.cpp at logger->log(), because logger has never been defined. I could solve this by adding logger = new Logger(). But I want to only create a new Logger instance, if none has been created in a program / library using this library. When an instance has been created already, I can use that by adding extern Logger logger;. But this will not work, when no instance has been created. Any suggestions (is it possible at all ?) ?
Note: I am using Gtkmm4 / Glibmm2.6 already, maybe there is a solution by using Gtk or Glib ...
First approach: Singleton
As discussed in the comments, you could use the Singleton design pattern
to acheive this. However, remember that this pattern has several drawbacks,
two of which are:
Singletons allow global access.
Singletons are hard to unit test.
Which are true problems when writing quality software. Also, for your particular
case, make sure to read this answer which explains how to make sure everything
is linked appropriately so you do not end up with multiple instances of your
singleton.
Second approach: dependency injection
I decided to post an answer here to illustrate another way of doing things that
solves the two issues mentionned above: dependency injection (DI). With DI,
you do not create your dependencies, you inject them through parameters. For
example, instead of:
Something::Something() {
auto logger = new Logger(); // Dependency creation (not injection)
logger->log("hello !");
}
you would have something like:
Something::Something(Logger* p_logger) { // Logger dependency injected through p_logger
p_logger->log("hello !");
}
Note that DI does not solve the "one instance" issue by itself. Care must be taken to
create your dependencies once (usually in your main) and then pass them around as
parameters to use them. However, the global access issue is resolved.
You can bring this to another level by abstracting your dependencies. For example,
you could write an interface to your Logger class and use this instead:
// Somewhere in your library:
class ILogger
{
public:
virtual ~ILogger() = default;
virtual void log(const std::string& p_message) = 0;
virtual void set_name(const std::string& p_name) = 0;
};
// In Logger.hpp:
class Logger : public ILogger {
public:
Logger();
void log(const std::string& p_message) override;
void set_name(const std::string& p_name) override;
private:
std::string m_name;
};
// In something.hpp/cpp:
Something::Something(ILogger* p_logger) { // Logger dependency injected through p_logger
p_logger->log("hello !");
}
To acheive this your main could look like this:
int main(int argc, char* argv[]) {
// Here, you create your logger dependency:
std::unique_ptr<ILogger> concreteLogger = std::make_unique<Logger>();
concreteLogger->set_name("frederic");
// Here, you inject it. From here on, you will inject it everywhere
// in your code. The using code will have no idea that under the hood,
// you really are using the Logger implementation:
some = new Something(concreteLogger.get());
// Note: if you use `new`, do not forget to use `delete` as well. Otherwise,
// check out std::unique_ptr, like above.
return 0;
}
The advantage of this is that you can now change the implementation of your logger
at any time whithout anything (except main) caring about it. You can also create
mocks of your logger in case you want to unit test Something. This is highly
more flexible that handling the singleton in your unit tests, which in term will
create all sorts of (hard to investigate/resolve) problems. This, in terms, solves
the second issue mentionned above.
Note that a possible drawback of DI is that you may end up having lots of
parameters, but in my opinion it is still superior to using singletons.
I want to create a library that holds multiple objects and takes care of them. However, if certain things happen to the objects then I want to be able to perform additional actions in the project that uses the library.
The following is a brief example of what I want to do:
// Library:
class LibraryClass {
public:
bool Init() { /* Blah. */ }
void Shutdown() { /* Blah blah. */ }
void Update() {
for( int i( 0); i < m_objects.size(); ++i) {
bool somethingHappened = m_objects[i].Update();
if( somethingHappened)
CallBackFunctionToMainProject( &m_objects[i]);
}
}
private:
std::vector<Objects> m_objects;
};
// Project that uses the library:
class Program {
public:
void Run() {
m_libClass = new LibraryClass();
m_libClass.Init();
while( true) {
m_libClass.Update();
OtherUpdateStuff();
}
m_libClass.Shutdown();
delete m_libClass;
}
private:
LibraryClass* m_libClass;
};
void CallBackFunctionToMainProject( Object* obj) {
// Do stuff.
}
So as you can see, I want the library to call the function that's declared in the main project, however I also want it to not complain if the function hasn't been declared in the main project.
Is it possible for me to do this? And if so, how? (If possible, I'd like to avoid the option of passing variables through to the library, such as a function pointer).
There are possible options but will have to pass/set something to the library to callback on.
Pass a function pointer from the main program (you've mentioned it).
Define an interface class in the library, which the main program will implement and pass it to the library (more elegant).
Register a function pointer or interface object some place where the library can access (just a level of indirection than passing directly)
Hope it helps.
Okay, so I know that static virtual functions don't exist for several reasons. I do believe, however, I have found a situation in which something mimicking them may be useful. As part of a group project for a class we must design a scripting core for a game engine. In order to keep things decoupled we want a class to be able to register its metatables (functions, members, etc) with the LuaState. Also, I could be way off here as this is my first time trying to implement anything of the sort.
So, in order to keep things generic we have an IScriptStateManager interface that contains pure virtual functions to register objects with the scripting languages global state, perform init and shutdown features, and has a couple other functions for DoFile and DoString. Then we have a LuaStateManager class that implements the functionality of this interface.
Now, in order to allow most game objects to be created in script without knowing about them ahead of time we also created an IScriptObject interface. If you want an object to be represented by the scripting system it should implement this interface. This interface includes a method that contains a method called register that derived classes can implement and will set up there metatables. So everything looks like this:
bool LuaStateManager::Register(IScriptObject* obj)
{
if (obj has not already been registered with global state)
{
obj->Register();
return true;
}
return false;
}
I'm sure you can see the problem. First and foremost we need and actual instantiation to register an object. Because of this we may be calling this function multiple times for a particular type of object, only to have it return true the first time and false every other time. While the overhead of this is minimal, it's a dead giveaway that something is wrong with the design.
So the issue arises. In this particular case we need the functionality of both a static method and a virtual method. Granted we could simply manually add static methods to each class and then call those once, but this couples objects to the scripting system. Any tips or help would be most welcome. Thanks
Provide access to the functionality of IScriptStateManager through a set of functions in an API class or a namespace.
ScriptStateManagerAPI.h:
namespace ScriptStateManagerAPI
{
// Function to register the active ScriptStateManager.
void setActiveScriptStateManager(IScriptStateManager* scriptStateManager);
// Function to register a ScriptObject.
bool registerScriptObject(IScriptObject* obj);
}
IScriptStateManager.h:
class IScriptStateManager
{
virtual bool registerScriptObject(IScriptObject* obj) = 0;
};
ScriptStateManagerAPI.cpp:
#include <IScriptStateManager.h>
namespace ScriptStateManagerAPI
{
static IScriptStateManager* activeScriptStateManager = nullptr;
void setActiveScripStatetManager(IScriptStateManager* scriptStateManager)
{
activeScriptStateManager = scriptStateManager;
}
bool registerScriptObject(IScriptObject* obj)
{
if ( activeScriptStateManager )
{
return activeScriptStateManager->registerScriptObject(obj);
}
else
{
// Deal with lack of an active IScriptStateManager.
return false;
}
}
}
LuaScriptManager.h:
#include <IScriptStateManager.h>
class LuaScriptManager : public IScriptStateManager
{
virtual bool registerScriptObject(IScriptObject* obj);
};
LuaScriptManager.cpp:
namespace
{
// Helper class in anonymous namespace to register a LuaScriptManager as
// the active IScriptStateManager at start up time.
struct Initializer
{
Initializer();
};
};
// Construct an Initializer at start up time.
static Initializer initializer;
Initializer::Initializer()
{
// Register a LuaScriptManager as the acive ScriptStateManager.
ScriptStateAPI::setActiveScriptStateManager(new LuaScriptManager());
}
bool LuaScriptManager::registerScriptObject(IScriptObject* obj)
{
if (obj has not already been registered with global state)
{
obj->Register();
return true;
}
return false;
}
You can use another ScriptStateManager in your application. Then you have to choose whether you can have only one ScriptStateManager at a time or not. If your application needs more than one ScriptStateManager at a time, you can change the static data as well as the interface in ScriptStateManagerAPI
ScriptStateManagerAPI.h:
namespace ScriptStateManagerAPI
{
// Function to register an active ScriptStateManager.
void registerActiveScriptStateManager(IScriptStateManager* scriptStateManager);
// Function to register a ScriptObject.
bool registerScriptObject(IScriptObject* obj);
}
ScriptStateManagerAPI.cpp:
#include <IScriptStateManager.h>
namespace ScriptStateManagerAPI
{
static std::set<IScriptStateManager*> activeScriptStateManagers;
void registerActiveScripStatetManager(IScriptStateManager* scriptStateManager)
{
activeScriptStateManagers.insert(scriptStateManager);
}
bool registerScriptObject(IScriptObject* obj)
{
// Figure out how to manage the return the values of each
// activeScriptManager.
for ( auto activeScriptManager, activeScriptStateManagers)
{
activeScriptManager->registerScriptObject(obj);
}
return true; //????
}
}
For a class, which is only defined in a header, I need a special behavior of one method for all instance of the class. It should be depending on a default value, which can be changed any time during runtime. As I do not want a factory class nor a central management class I came up with that idea:
class MyClass
{
public:
void DoAnything() // Methode which should be act depending on default set.
{
// Do some stuff
if(getDefaultBehaviour())
{
// Do it this way...
}
else
{
// Do it that way...
}
}
static bool getDefaultBehaviour(bool bSetIt=false,bool bDefaultValue=false)
{
static bool bDefault=false;
if(bSetIt)
bDefault=bDefaultValue;
return bDefault;
}
};
It works, but it looks a little awkward. I wonder if there is a better way following the same intention.
In the case where I want to use it the software already created instances of that class during startup and delivered them to different parts of the code. Eventually the program gets the information how to treat the instances (for e.g. how or where to make themselves persistent). This decision should not only affect new created instances, it should affect the instances already created.
I'd advise to use a simple method to simulate a static data member, so the usage becomes more natural:
class MyClass
{
public:
// get a reference (!) to a static variable
static bool& DefaultBehaviour()
{
static bool b = false;
return b;
}
void DoAnything() // Methode which should be act depending on default set.
{
// Do some stuff
if(DefaultBehaviour())
{
// Do it this way...
}
else
{
// Do it that way...
}
}
};
where the user can change the default at any time with
MyClass::DefaultBehaviour() = true;
My thanks to Daniel Frey with his answer which I already marked as the best. I wanted to add my final solution which is based on the answer from Frey. The class is used by some c++ beginners. As I told them to use always getter and setter methods, the way described by Frey looks very complex to beginners ("uuuh, I can give a function a value?!?!"). So I wrote the class like followed:
class MyClass
{
public:
// get a reference (!) to a static variable
static bool& getDefaultBehaviour()
{
static bool b = false;
return b;
}
static void setDefaultBehaviour(bool value)
{
getDefaultBehaviour()=value;
}
void DoAnything() // Methode which should be act depending on default set.
{
// Do some stuff
if(getDefaultBehaviour())
{
// Do it this way...
}
else
{
// Do it that way...
}
}
};
for the user, I looks now like a usual getter and setter.
I've developed a game on Cocos2d-x v2 platform
I started on Android, after completely finishing the coding on Eclipse I used the same code on Xcode to create and iOS version.
After adding all the required libraries, I succeeded in compiling the code. However, the game hangs the moment it runs on an iOS device, although it runs without any problem on Android.
I tried both the emulator and an iPod, but I always get an EXC_BAD_ACCESS when accessing a static member from a static method. The static member would always point to 0x0!!
Here's an excerpt from the code:\
AppDelegate.cpp
#include "AppDelegate.h"
#include "NASEncData.h"
AppDelegate::AppDelegate()
{
ep = NASEncData::sharedUserData();
}
NASEncData.h
namespace CocosNas
{
class NASEncData : public CCObject
{
public:
static NASEncData* sharedUserData();
private:
NASEncData();
static void initXMLFilePath();
static std::string m_sFilePath;
}
}
NASEncData.cpp
#include "NASEncData.h"
NASEncData* NASEncData::sharedUserData()
{
initXMLFilePath();
// only create xml file one time
// the file exists after the programe exit
if ((! isXMLFileExist()) && (! createXMLFile()))
{
return NULL;
}
if (! m_spUserData)
{
m_spUserData = new NASEncData();
}
return m_spUserData;
}
void NASEncData::initXMLFilePath()
{
if (! m_sbIsFilePathInitialized)
{
m_sFilePath += CCFileUtils::sharedFileUtils()->getWriteablePath() + NASENCDATA_XML_FILE_NAME; <----error happens here
m_sbIsFilePathInitialized = true;
}
}
Based on the comments on your question, your problem could be the initialization order of static data. To be more specific, I think it is possible that the static AppDelegate instance gets created and initialized before the static members in the NASEncData. And this problem could also explain the fact that you are seeing different behavior on different platform, because the initialization order of unrelated static data are compiler and linker dependent.
To fix this, you could change your NASEncData like this: (note that this is only one possible fix, although if the initialization order of statics is really your problem, I think this is the simplest and best solution, apart from redesigning your code so that you don't have to rely on static members.)
NASEncData.h
namespace CocosNas
{
class NASEncData : public CCObject
{
public:
static NASEncData* sharedUserData();
private:
NASEncData();
static void initXMLFilePath();
// Note how the stuff below this line have changed
struct StaticData
{
std::string m_sFilePath;
// Put other static members here
// (e.g. m_sbIsFilePathInitialized, m_spUserData, etc.)
// Put a proper constructor here if needed
};
static StaticData & getStaticData ()
{
static StaticData s_data;
return s_data;
}
}
}
NASEncData.cpp
void NASEncData::initXMLFilePath()
{
if (! m_sbIsFilePathInitialized)
{
// Note the change in accessing m_sFilePath
// You should access all your static members like this
getStaticData().m_sFilePath +=
CCFileUtils::sharedFileUtils()->getWriteablePath() +
NASENCDATA_XML_FILE_NAME;
getStaticData().m_sbIsFilePathInitialized = true;
}
}
What this does in ensure that when you try and access your static member data, they have already been initialized. This happens because all your static member data are now defined inside a function as static, and for accessing them you have to call that function, and the compiler generates code to make sure that the first time that function is invoked (and only the first time) your data is constructed and initialized properly, which in turn means that the first time you actually try to access this data, whenever and wherever that may be from, your data is properly initialized.
It was indeed an initialization problem I just had to move the code from the construction to bool AppDelegate::applicationDidFinishLaunching() and it worked!