Russian Qt Forum
Сентябрь 22, 2024, 21:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 4   Вниз
  Печать  
Автор Тема: Сигналы и слоты в плагинах  (Прочитано 20940 раз)
lighting
Гость
« : Август 20, 2012, 09:28 »

Есть задача, программа должна управлять различными железками. Для унификации протокол общения с каждой конкретной железкой выносится в отдельный плагин и подгружается по мере надобности. Насколько я понял интерфейс не может наследоваться от QObject следовательно сигналы и слоты ему недоступны. Со слотами проблема решаемая - их можно вызывать как методы, а вот как быть с сигналами, как получать инфу от плагина?
Записан
Странник
Гость
« Ответ #1 : Август 20, 2012, 09:46 »

Есть задача, программа должна управлять различными железками. Для унификации протокол общения с каждой конкретной железкой выносится в отдельный плагин и подгружается по мере надобности. Насколько я понял интерфейс не может наследоваться от QObject следовательно сигналы и слоты ему недоступны. Со слотами проблема решаемая - их можно вызывать как методы, а вот как быть с сигналами, как получать инфу от плагина?
может, доступны - хотя де юре интерфейс должен быть чисто абстрактным (если это требование не отменили в последних версиях, конечно), де факто вы можете без проблем наследоваться от QObject. но если вы борец за расовую чистоту, ваш интерфейс может возвращать указатель на наследника QObject.
Записан
Sancho_s_rancho
Гость
« Ответ #2 : Август 20, 2012, 11:36 »

Интерфейс без наследования от QObject, но с
Код:
virtual QObject* pluginObject() = 0;
А в плагине
Код:
class MyClass : public QObject, public ModuleInterface
{
    Q_OBJECT
    Q_INTERFACES(ModuleInterface)
public:
virtual QObject* pluginObject() { return this; }
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #3 : Август 20, 2012, 15:42 »

Если не нравится использование этого метода (мне не нравится):
Код
C++ (Qt)
virtual QObject* pluginObject() { return this; }
 
можно в основной программе делать примерно так:
Код
C++ (Qt)
QPluginLoader loader("plugin");
connect(loader.instance(), SIGNAL(pluginSignal()), SLOT(appSlot()));
 
Записан
andrew.k
Гость
« Ответ #4 : Август 20, 2012, 16:00 »

можно в основной программе делать примерно так:
Код
C++ (Qt)
QPluginLoader loader("plugin");
connect(loader.instance(), SIGNAL(pluginSignal()), SLOT(appSlot()));
 
Чтобы экземпляр плагина мог испускать сигналы (по условию задачи), он все-таки должен быть наследован от QObject.
А т.к. сигналы как и все прочее скорее всего будут унифицированы, наследование должно присутствовать на уровне интерфейса.
Можно конечно перенести объявление сигналов в реализацию интерфейса, но не думаю, что это будет красиво, скорее наоборот.

Поэтому не вижу ничего страшного или некрасивого в том, чтобы интерфейс наследовался от QObject. Технология такая, что естественно, то не безобразно.
Нужно просто в этом интерфейсе делать защищенный конструктор (при необходимости).
« Последнее редактирование: Август 20, 2012, 16:55 от andrew.k » Записан
lighting
Гость
« Ответ #5 : Август 20, 2012, 16:27 »

Пробую объявить интерфейс так:

Код
C++ (Qt)
#ifndef INTERFACES_H
#define INTERFACES_H
#include <QObject>
 
class QString;
class CameraInterface : public QObject
{
   Q_OBJECT
public:
   virtual ~CameraInterface() {}
   virtual void powerOn();
   ...
   virtual void extendedCommand(QString command);
 
signals:
   void powerStateCahnged(bool state);
   void backlightStateChanged(bool state);
};
 
Q_DECLARE_INTERFACE(CameraInterface, "ru.myCompany.myApp.cameraInterface/1.0")
 
#endif // INTERFACES_H
 

При попытке сборки валятся ошибки вида:
debug/moc_interfaces.o:moc_interfaces.cpp:(.rdata$_ZTV15CameraInterface[vtable for CameraInterface]+0x38): undefined reference to `CameraInterface::powerOn()'
количеством равным кол-ву виртуальных методов. Насколько я понимаю компилятор пытается найти реализацию вирутальных функций, но зачем он это делает мне не понятно.

Читал вот эту тему http://www.prog.org.ru/topic_8357_0.html никак не могу взять в толк для чего Dendy и Константин советуют в интерфейсе только передавать указатель на создаваемый класс, а не указывать список доступных методов. Я себе представлял что в интерфейсе надо собирать общие для поддерживающих протокол железок методы, чтобы вызывающему плагин приложению было наплевать на реализацию класса для конкретной железки, а советуют делать наоборот  В замешательстве
Записан
andrew.k
Гость
« Ответ #6 : Август 20, 2012, 16:36 »

Насколько я понимаю компилятор пытается найти реализацию вирутальных функций, но зачем он это делает мне не понятно.
Он же не знает, что ты недоучил с++

методы должны быть абстрактными, не?
« Последнее редактирование: Август 20, 2012, 16:38 от andrew.k » Записан
lighting
Гость
« Ответ #7 : Август 20, 2012, 16:41 »

да, не все то абстрактно, что виртуально Улыбающийся
Записан
andrew.k
Гость
« Ответ #8 : Август 20, 2012, 16:43 »

да, не все то абстрактно, что виртуально Улыбающийся
Заодно QString передавай по константной ссылке.
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #9 : Август 20, 2012, 16:46 »

Чтобы экземпляр плагина мог испускать сигналы (по условию задачи), он все-таки должен быть наследован от QObject.
А я нигде и не утверждал, что MyClass не не должен наследоваться от QObject, как раз наоборот. Я имел ввиду, что метод pluginObject() - лишний, потому, что loader.instance() возвращает ровно то же, что pluginObject().

Пробую объявить интерфейс так:
class CameraInterface : public QObject
CameraInterface НЕ ДОЛЖЕН наследоваться от QObject! От QObject надо наследоваться классом, который реализует абстрактные методы из CameraInterface (см. пример от Sancho_s_rancho с классом MyClass).
Записан
andrew.k
Гость
« Ответ #10 : Август 20, 2012, 16:48 »

CameraInterface НЕ ДОЛЖЕН наследоваться от QObject! От QObject надо наследоваться классом, который реализует абстрактные методы из CameraInterface (см. пример от Sancho_s_rancho с классом MyClass).
Если ты так решил, это не значит, что все должны так делать.
Каким раком тогда moc сгенерит код для сигналов и слотов интерфейса?
Еще как ДОЛЖЕН.
« Последнее редактирование: Август 20, 2012, 16:52 от andrew.k » Записан
lighting
Гость
« Ответ #11 : Август 20, 2012, 16:55 »

CameraInterface НЕ ДОЛЖЕН наследоваться от QObject! От QObject надо наследоваться классом, который реализует абстрактные методы из CameraInterface (см. пример от Sancho_s_rancho с классом MyClass).
andrew.k меня опередил, но я добавлю - если CameraInterface не будет наследоваться от QObject то как тогда мое приложение использующее плагины узнает о том какие что плагин будет посылать сигналы. Собственно заморочку с плагинами я затеял именно для того чтобы написать нужное кол-во плагинов реализующих конкретный функционал (SonyCamera, AxisCamera, TandbergCamera и т.п.) без необходимости правок в основной программе. Она не должна знать о том что есть все это многообразие, а работать должна со всеми ими через CameraInterface.
Записан
andrew.k
Гость
« Ответ #12 : Август 20, 2012, 17:23 »

Можно конечно не наследовать от QObject, а добавить метод возвращающий экземпляр абстрактного рабочего класса (а реализация будет его в наследниках).
Что-нибудь типа
Код
C++ (Qt)
virtual BaseCameraWorker * createWorkerObject() = 0;
Если это действительно необходимо, по соображениям гибкости, то почему нет. Это уже должен автор решать, надо оно ему или нет.
Но не вижу в этом подходе преимуществ (для рассматриваемого примера), ровно как и недостатков в рассматриваемом выше подходе. Меня не пугает интерфейс наследованный от QObject.

Можно абстрагироваться сколько угодно в глубь и в ширь, но как говорится чем круче джип, тем дальше ехать трактору)
« Последнее редактирование: Август 20, 2012, 17:28 от andrew.k » Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #13 : Август 20, 2012, 17:57 »

Каким раком тогда moc сгенерит код для сигналов и слотов интерфейса?
Еще как ДОЛЖЕН.
Давайте-ка ещё раз и по-спокойнее. Наследоваться от QObject (а так же от CameraInterface) будут классы SonyCamera, AxisCamera, TandbergCamera и т.д. Для них же, а не для CameraInterface, moc сгенерит код для всех их сигналов и слотов. Основному приложению достаточно знать только методы, имеющиеся в CameraInterface и общие для ВСЕХ его наследников сигналы/слоты. В основном приложении на этапе компиляции совсем не нужны moc реализации всего того, что он нагенерит для плагинов.

Вот даже пример набросал.
« Последнее редактирование: Август 20, 2012, 18:07 от xokc » Записан
andrew.k
Гость
« Ответ #14 : Август 20, 2012, 18:06 »

Каким раком тогда moc сгенерит код для сигналов и слотов интерфейса?
Еще как ДОЛЖЕН.
Давайте-ка ещё раз и по-спокойнее. Наследоваться от QObject (а так же от CameraInterface) будут классы SonyCamera, AxisCamera, TandbergCamera и т.д. Для них же, а не для CameraInterface, moc сгенерит код для всех их сигналов и слотов. Основному приложению достаточно знать только методы, имеющиеся в CameraInterface и общие для ВСЕХ его наследников сигналы/слоты. В основном приложении на этапе компиляции совсем не нужны moc реализации всего того, что он нагенерит для плагинов.

Код
C++ (Qt)
class CameraInterface
{
//Q_SIGNALS:
//   void initDone();
// Если тут не будут описаны сигналы
};
 
class SonyCamera : public QObject, public CameraInterface
{
 void doInit()
 {
   ...
  emit initDone();
   // то тут ты не сможешь испускать этот сигнал.
 }
 
// и тогда тебе надо будет описывать его тут:
Q_SIGNALS:
  void initDone();
};
 
class AxisCamera : public QObject, public CameraInterface
{
...
// и еще тут:
Q_SIGNALS:
  void initDone();
};
 
class TandbergCamera : public QObject, public CameraInterface
{
...
// и еще тут:
Q_SIGNALS:
  void initDone();
};
 
//И во всех остальных классах придется делать копипасту.
 
 
« Последнее редактирование: Август 20, 2012, 18:10 от andrew.k » Записан
Страниц: [1] 2 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.297 секунд. Запросов: 22.