Using a Singleton Class across a Qt Application and its Plugins

空扰寡人 提交于 2019-12-22 18:13:36

问题


I'm trying to use a Singleton Class (its a program-wide debug logger called 'PrisLog') across my Qt Application. The program also has plugins. I want to make my singleton class available to those plugins, but this doesn't work. From what I can tell, trying to use the class in the plugin results in another instance being created.

-The singleton class is just a *.cpp and *.h file, nothing else. I've linked both my main application and the plugin to these files individually... is this the right way to do it?

-I've attached my singleton class's code below, though I think I've created the class correctly. If I use it from within separate classes in my main application, it works as expected (one instance).

EDIT: Linking both the application and plugin to the same static lib (the singleton class) works. Here's how my qmake *.pro files looked:

MySingletonLib.pro

TEMPLATE = lib

CONFIG += staticlib

HEADERS += \ mysingletonlib.h

SOURCES += \ mysingletonlib.cpp

MyPlugin.pro (also incl #include mysingletonlib.h in myplugin.h)

INCLUDEPATH += path/to/MySingletonLib

LIBS += -Lpath/to/MySingletonLib -lMySingletonLib

MyPlugin.pro (also incl #include mysingletonlib.h in myapp.h)

INCLUDEPATH += path/to/MySingletonLib

LIBS += -Lpath/to/MySingletonLib -lMySingletonLib

And the original code:

#ifndef PRISLOG_H
#define PRISLOG_H

#include <QFile>
#include <QDir>
#include <QString>
#include <QMutex>
#include <QDebug>
#include <QMutexLocker>
#include <QTextStream>
#include <QDateTime>

// PrisLog (singleton) class definition
class PrisLog
{

public:
    static PrisLog* Instance();

    void SetLogsPath(QString);
    QString GetLogsPath();

    void SetDebugDestination(QString);
    void SetElmRxDestination(QString);
    void SetElmTxDestination(QString);
    void SetDlgDestination(QString);

    QTextStream* GetDebugStream();
    QTextStream* GetElmRxStream();
    QTextStream* GetElmTxStream();
    QTextStream* GetDlgStream();

    QMutex* GetDebugMutex();

private:
    PrisLog();                          // private constructor
    PrisLog(const PrisLog&);            // prevent copy constructor
    PrisLog& operator=(const PrisLog&); // prevent assignment

    static PrisLog* m_Instance;
    static bool m_InitFlag;

    QString m_appPath;

    QFile m_DebugFile;
    QTextStream m_DebugStream;
    QMutex m_DebugMutex;

    QFile m_ElmRxFile;
    QTextStream m_ElmRxStream;

    QFile m_ElmTxFile;
    QTextStream m_ElmTxStream;

    QFile m_DlgFile;
    QTextStream m_DlgStream;

};

// thread-UNSAFE writer, but less expensive
// use: single stream <--> single thread!
class PrisLogWriter
{

public:
    PrisLogWriter(QTextStream*);
    ~PrisLogWriter();

    QTextStream* m_stream;
};

// thread-UNSAFE writer, but less expensive
// this version does not include any formatting
// use: single stream <--> single thread!
class PrisLogRawWriter
{

public:
    PrisLogRawWriter(QTextStream*);
    ~PrisLogRawWriter();

    QTextStream* m_stream;
};

// thread-safe writer
// use: single stream <--> many threads
class PrisLogSafeWriter
{

public:
    PrisLogSafeWriter(QTextStream*, QMutex*);
    ~PrisLogSafeWriter();

    QTextStream* m_stream;

private:
    QMutex* m_mutex;
};


#define PRISLOGDEBUG (*(PrisLogSafeWriter(PrisLog::Instance()->GetDebugStream(), PrisLog::Instance()->GetDebugMutex()).m_stream))
#define PRISLOGELMRX (*(PrisLogWriter(PrisLog::Instance()->GetElmRxStream()).m_stream))
#define PRISLOGELMTX (*(PrisLogWriter(PrisLog::Instance()->GetElmTxStream()).m_stream))
#define PRISLOGDLG (*(PrisLogRawWriter(PrisLog::Instance()->GetDlgStream()).m_stream))


#endif // PRISLOG_H

回答1:


I think you should take this class to a statically linked, but separeted shared dll/so.

If your host application does not use this class, the linker simply won't link it into the binary and your plugin could not use it. Additionally: your binary has no library class interface.




回答2:


You need to make sure, that only one instance exists. The safest is, that the cpp is compiled only once in the overall exe. To make sure that the other DLLs can call PrisLog::Instance, this class/function (i.e. all public methods if PrisLog) needs to be declared with __declspec(dllexport), even if it is located within the exe. The DLLs can then dynamically find the object and method.

BTW: Why don't you use the logging from Qt?



来源:https://stackoverflow.com/questions/6689370/using-a-singleton-class-across-a-qt-application-and-its-plugins

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!