Использование класса Singleton в приложении Qt и его плагинах - PullRequest
1 голос
/ 14 июля 2011

Я пытаюсь использовать Singleton Class (это отладочный журнал для всей программы под названием PrisLog) в моем приложении Qt. В программе также есть плагины. Я хочу сделать мой синглтон-класс доступным для этих плагинов, но это не работает. Из того, что я могу сказать, попытка использовать класс в плагине приводит к созданию другого экземпляра.

- Синглтон-класс - это просто файл * .cpp и * .h, больше ничего. Я связал свое основное приложение и плагин с этими файлами по отдельности ... это правильный способ сделать это?

-Я прикрепил код моего синглтон-класса ниже, хотя я думаю, что создал класс правильно. Если я использую его из отдельных классов в своем основном приложении, он работает как положено (один экземпляр).

РЕДАКТИРОВАТЬ: Работает связывание приложения и плагина с одной и той же статической библиотекой (класс singleton). Вот как выглядели мои файлы qmake * .pro:

MySingletonLib.pro

ШАБЛОН = lib

CONFIG + = staticlib

HEADERS + = \ mysingletonlib.h

ИСТОЧНИКИ + = \ mysingletonlib.cpp

MyPlugin.pro (также включает #include mysingletonlib.h в myplugin.h)

INCLUDEPATH + = путь / к / MySingletonLib

LIBS + = -Lpath / to / MySingletonLib -lMySingletonLib

MyPlugin.pro (также включает #include mysingletonlib.h в myapp.h)

INCLUDEPATH + = путь / к / MySingletonLib

LIBS + = -Lpath / to / MySingletonLib -lMySingletonLib

И оригинальный код:

#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

Ответы [ 2 ]

0 голосов
/ 14 июля 2011

Вы должны убедиться, что существует только один экземпляр. Самое безопасное, что cpp компилируется только один раз в общем exe-файле. Чтобы другие библиотеки DLL могли вызывать PrisLog :: Instance, этот класс / функцию (т. Е. Все открытые методы, если PrisLog) необходимо объявить с помощью __declspec (dllexport), даже если он находится внутри exe. Затем библиотеки DLL могут динамически находить объект и метод.

Кстати: почему вы не используете протоколирование из Qt?

0 голосов
/ 14 июля 2011

Я думаю, вы должны отнести этот класс к статически связанным, но разделенным разделяемым dll / т.

Если ваше хост-приложение не использует этот класс, компоновщик просто не будет связывать его с двоичным файлом, и ваш плагин не сможет его использовать. Дополнительно: ваш двоичный файл не имеет интерфейса класса библиотеки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...