Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Sharing singletons between the main application and loaded plugins



  • I have my main application and a shared library/plugin that is loaded at runtime using QPluginLoader.

    Both use a singleton logger for logging events.

    The main application initializes the logger. The logger is implemented as a static member variable of the logger class.

    However, when loading my plugin at runtime, it appears that the plugin references a different instance of the global logger.

    Is there a way to make it so that the plugin references the global logger that was initialized by the main application? I've tried using the different QPluginLoader hints, but none of them achieved my desired result.


  • Lifetime Qt Champion

    Hi,

    Where do you implement that Singleton ?
    A static variable in some file doesn't make a singleton. Did you follow the pattern properly when implementing it ?



  • @sgaist The singleton is a static member variable of the logger class. The logger class has a static function initialize(some_args).

    In the app's main(), I initialize that instance with logger::intialize(some_args). Then all access to the logger is done through logger::instance(). Both the app and the plugin use logger::instance() to access the singleton to log events.

    Note:

    • It works as expected when I compile in debug mode, but doesn't work when compiled in release mode.
    • The logger is implemented in a static lib that is linked to by both the main app and the plugin

    Minimal example:

    logger.hpp

    class Logger : public QObject
    {
       Q_OBJECT
       Q_DISABLE_COPY(Logger)
    public:
       static void initialize(QCoreApplication *parent);
       static Logger *instance() { return global; }
    
       void logEvent(const QString & msg);
    
       ~Logger() override;
    
    protected:
       explicit Logger(QCoreApplication *app);
    
    private:
       static Logger *global;
    };
    

    logger.cpp

    Logger *Logger::global = nullptr;
    
    void Logger::initialize(QCoreApplication *parent)
    {
       if (global == nullptr)
       {
          global = new Logger(parent);
       }
    }
    

    main.cpp

    int main()
    {
        QApplication app;
        Logger::initialize(&app);
    }
    

    In the app if I do:

    qDebug() << Logger::instance()
    

    It outputs the address of the Logger instance

    In the plugin if I do:

    qDebug() << Logger::instance()
    

    It outputs 0

    When compiled in debug mode, both output the address to the same instance.


  • Lifetime Qt Champion

    @btse said in Sharing singletons between the main application and loaded plugins:

    The logger is implemented in a static lib that is linked to by both the main app and the plugin

    And here is your problem: make it a shared library.
    The plugin and main application have their own copy of the library and thus its symbols.



  • @sgaist Got it, thanks!

    I think I'll try to move away from the singleton pattern first and get it working that way.


Log in to reply