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

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

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: Сигналы и слоты в плагинах  (Прочитано 20939 раз)
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



Просмотр профиля
« Ответ #30 : Август 21, 2012, 12:38 »

Что-то изменится? Кошерности прибавится?
Под "кошерностью" в данном случае понимаю строгое следование документации Qt.
Но раз они сами себе позволяют ей не следовать и у вас
Все работает. В общем ОК.
то и спорить в общем-то не о чем.
Записан
lighting
Гость
« Ответ #31 : Август 21, 2012, 21:23 »

Мы путаемся в терминологии. Интерфейс с точки зрения С++ - класс, состоящий исключительно из абстрактных методов. У него не может быть сигналов и слотов, поскольку они - принадлежность QObject.
Это понятно, в данном случае вопрос сугубо практический. Я уже сейчас накидал порядка 15 интерфейсов для своих нужд, и думаю их число будет расти. Если делать все "кошерно" то это будет уже 30 классов, и у меня возникли сомнения - надо-ли плодить столько сущностей. Собственно вопрос в том какие плюсы и минусы у обоих подходов, чего я лишусь если не буду выделять отдельные абстрактные интерфейсы и отдельные base классы?[/quote]
Если у тебя всё работает и без них (т.е. интерфейс в твоём понимании - это объект, порождённый от QObject и содержащий некий набор абстрактных методов) и тебя это устраивает - можешь не заморачиваться "кошерными" подходами.
Ну меня-то все устраивает, но вот будет ли все работать это как раз и вопрос. Не хочется наступать на грабли в середине пути, поэтому и спросил у людей которые уже возможно прошли по нему раньше меня - есть-ли в таком подходе скрытые грабли? Улыбающийся
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #32 : Август 21, 2012, 22:08 »

Это понятно, в данном случае вопрос сугубо практический. Я уже сейчас накидал порядка 15 интерфейсов для своих нужд, и думаю их число будет расти.
А откуда такое обилие? Они что, не укладываются в единый интерфейс/класс плагина или как?
Записан
lighting
Гость
« Ответ #33 : Август 21, 2012, 22:47 »

А откуда такое обилие? Они что, не укладываются в единый интерфейс/класс плагина или как?
Ну так железки разные, функционал и возможности у них тоже разные. Напр. камеры могут Pan/Tilt  Zoom и т.п. видеокоммутатор может переключать входы на выходы и т.д.
Если конечно рассматривать "кошерный" вариант то можно обойтись одним интерфейсом для всего, но кроме ссылки на конкретный базовый класс тогда в этот интерфейс ничего не засунешь.
Записан
andrew.k
Гость
« Ответ #34 : Август 21, 2012, 23:12 »

Провел эксперимент.
Если убрать макрос Q_DECLARE_INTERFACE, то проект плагина (я взял проект хокса для тестов) не компилится.
Ругается, что у интерфейса нет макроса Q_OBJECT. Если его добавить, то ругается, что не может преобразовать интерфейс к QObject *
Дальше добавляю наследование от QObject. И больше не ругается. И плагин компилится.
Хоть использовать его и нельзя, т.к. макрос Q_DECLARE_INTERFACE определяет какие-то функции, которые видимо необходимы метаобъектной системе, и без него система работать не будет.
Отсюда я делаю вывод, что интерфейс в Qt имеет все-таки метаобъектную природу и рассматривается метаобъектной системой как QObject.
Таким образом интерфейс в Qt не равен чистому интерфейсу c++. Moc используя макросы его "тюнингует".
И отсюда главный вывод, что использование сигналов в интерфейсах Qt допустимо.

PS. что делает сам макрос мне не очень понятно. Определяет какие-то функции. Мне не понятен синтаксис препроцессора.
Код
C++ (Qt)
#  define Q_DECLARE_INTERFACE(IFace, IId) \
   template <> inline const char *qobject_interface_iid<IFace *>() \
   { return IId; } \
   template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
   { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \
   template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
   { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0)); }
Записан
xokc
Птица говорун
*****
Offline Offline

Сообщений: 976



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

Я уже сейчас накидал порядка 15 интерфейсов для своих нужд, и думаю их число будет расти. Если делать все "кошерно" то это будет уже 30 классов
То есть 15 различных ТИПОВ устройств? Или всё таки 15 вариантов одного и того же типа (камер, насколько я понимаю)?

Ну меня-то все устраивает, но вот будет ли все работать это как раз и вопрос. Не хочется наступать на грабли в середине пути, поэтому и спросил у людей которые уже возможно прошли по нему раньше меня - есть-ли в таком подходе скрытые грабли? Улыбающийся

В моих проектах, и это понятно, я использую промежуточный класс. Причём он покрывает общий функционал наследников (в моём случае - это около 50 различных вариантов радиоприёмных устройств, подключаемых к COM порту) и лежит в отдельной DLL. Кстати, в этой же DLL скрыт и собственно код для работы с COM-портом.
Поскольку в этом случае в плагинах остаётся только тот функционал, который и отличает одно устройство от другого, то они получаются очень компактными, а их общую логику я могу изменять заменой той самой DLL без перекомпиляции плагинов.
Схема работает в реальных проектах года примерно три, пережила смену нескольких версий Qt и перспектив её пересматривать у меня оснований нет.

PS. что делает сам макрос мне не очень понятно. Определяет какие-то функции. Мне не понятен синтаксис препроцессора.
Ну так судя по всему он и добавляет самое главное - преобразование интерфейсного наследника к классу QObject.
« Последнее редактирование: Август 22, 2012, 08:19 от xokc » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


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

Ну так судя по всему он и добавляет самое главное - преобразование интерфейсного наследника к классу QObject.
Ну "в общих чертах" да, но сам бы такое я написать не смог. Что такое template <>  Непонимающий

Ну так железки разные, функционал и возможности у них тоже разные. Напр. камеры могут Pan/Tilt  Zoom и т.п. видеокоммутатор может переключать входы на выходы и т.д.
Хмм.. ну а тогда в чем смысл плагинов что обычно подразумевает расширение возможностей без изменений хоста? Не лучше ли делать это статик либой, возможно вынося в плагины только независимую часть (как советует  xokc) пусть и недостаточную для поддержки "всего".
Записан
andrew.k
Гость
« Ответ #37 : Август 22, 2012, 10:32 »

В моих проектах, и это понятно, я использую промежуточный класс. Причём он покрывает общий функционал наследников (в моём случае - это около 50 различных вариантов радиоприёмных устройств, подключаемых к COM порту) и лежит в отдельной DLL. Кстати, в этой же DLL скрыт и собственно код для работы с COM-портом.
Поскольку в этом случае в плагинах остаётся только тот функционал, который и отличает одно устройство от другого, то они получаются очень компактными, а их общую логику я могу изменять заменой той самой DLL без перекомпиляции плагинов.
Схема работает в реальных проектах года примерно три, пережила смену нескольких версий Qt и перспектив её пересматривать у меня оснований нет.
Никто ж не говорил, что она плохая. Не плохая, ни хорошая, имхо подходы по сути одинаковы. Только в одном случае, вид с боку.
Записан
lighting
Гость
« Ответ #38 : Август 23, 2012, 11:36 »

То есть 15 различных ТИПОВ устройств? Или всё таки 15 вариантов одного и того же типа (камер, насколько я понимаю)?
15 различных типов - камеры, видеокоммутаторы, устройства отображения и т.д. И в каждом типе может быть 1-10 различных конкретных железок, напр. камеры от sony, axis, polycom и т.д.
Хмм.. ну а тогда в чем смысл плагинов что обычно подразумевает расширение возможностей без изменений хоста? Не лучше ли делать это статик либой, возможно вынося в плагины только независимую часть (как советует  xokc) пусть и недостаточную для поддержки "всего".
Чтобы было понятнее опишу суть проблемы детальнее. Есть набор различного оборудования которым надо управлять, оборудование это различных типов, и различных вендоров в пределах одного типа. Все это оборудование образует единое целое - мультимедийная студия, которой необходимо управлять целиком. Таких студий с различным набором железок много, и моя цель - написать программу, которая будет брать из конфига список оборудования, характерного для данной конкретной студии и имея интерфейсы к типам устройств и плагины для каждой конкретной железки управлять ими всеми. Причем этой самой программе не нужно знать что есть конкретные железки, скажем камера Sony EVI HD 7, ей достаточно знать что есть интерфейс CameraInterface и получив из конфига имя плагина для данной железки создать экземпляр класса который будет ею управлять. В таком случае для адаптации к конкретному набору оборудования необходимо будет только создать соответствующий конфиг и дописать необходимые плагины для железок, изменения самой программы не потребуется.
« Последнее редактирование: Август 23, 2012, 11:44 от lighting » Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #39 : Август 23, 2012, 11:50 »

Ну "в общих чертах" да, но сам бы такое я написать не смог. Что такое template <>  Непонимающий
Специализация шаблона:
http://www.parashift.com/c++-faq/template-specialization.html
http://www.parashift.com/c++-faq/template-specialization-example.html
Записан
andrew.k
Гость
« Ответ #40 : Август 23, 2012, 12:52 »

Ну "в общих чертах" да, но сам бы такое я написать не смог. Что такое template <>  Непонимающий
Специализация шаблона:
http://www.parashift.com/c++-faq/template-specialization.html
http://www.parashift.com/c++-faq/template-specialization-example.html
О спасибо! А то не нашел.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #41 : Август 23, 2012, 14:50 »

Ну "в общих чертах" да, но сам бы такое я написать не смог. Что такое template <>  Непонимающий
Специализация шаблона:
http://www.parashift.com/c++-faq/template-specialization.html
http://www.parashift.com/c++-faq/template-specialization-example.html
С этим я в курсе, даже сам неск раз применял. Но я думал сначала нужна полная спецификация класса (template <class T>) а потом уже специализация (template <>). А где же у них полная? Или можно и без полной? Словом - растерялся солдат  Улыбающийся

Спасибо
Записан
andrew.k
Гость
« Ответ #42 : Август 23, 2012, 15:15 »

Ну "в общих чертах" да, но сам бы такое я написать не смог. Что такое template <>  Непонимающий
Специализация шаблона:
http://www.parashift.com/c++-faq/template-specialization.html
http://www.parashift.com/c++-faq/template-specialization-example.html
С этим я в курсе, даже сам неск раз применял. Но я думал сначала нужна полная спецификация класса (template <class T>) а потом уже специализация (template <>). А где же у них полная? Или можно и без полной? Словом - растерялся солдат  Улыбающийся
Полная находится в qobject.h
Код
C++ (Qt)
template <class T>
inline T qobject_cast(QObject *object)
{
#if !defined(QT_NO_QOBJECT_CHECK)
   reinterpret_cast<T>(object)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object));
#endif
   return static_cast<T>(reinterpret_cast<T>(object)->staticMetaObject.cast(object));
}
 
template <class T>
inline T qobject_cast(const QObject *object)
{
#if !defined(QT_NO_QOBJECT_CHECK)
   reinterpret_cast<T>(object)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
#endif
   return static_cast<T>(reinterpret_cast<T>(object)->staticMetaObject.cast(object));
}
 
 
template <class T> inline const char * qobject_interface_iid()
{ return 0; }
 
Если, конечно, я правильно все понял.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


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

С этим я в курсе, даже сам неск раз применял. Но я думал сначала нужна полная спецификация класса (template <class T>) а потом уже специализация (template <>). А где же у них полная? Или можно и без полной?
Полная в qobject.h:
Код
C++ (Qt)
template <class T> inline const char * qobject_interface_iid()
{ return 0; }
Ну а вообще объявление, насколько я помню, обязательно, а обобщённая реализация нет, могут быть одни специализации.
Записан
lighting
Гость
« Ответ #44 : Сентябрь 07, 2012, 15:50 »

Не думал что придется возвращаться к этой теме, но пришлось - при попытке добавить наследование интерфейса от QObject получаю ошибку при сборке плагина QObject is ambiguous base of [имя плагина]. Насколько я понял компилер не знает какой из конструкторов QObject ему использовать. andrew.k подскажи как ты решал эту проблему?
Интерфейс:
Код
C++ (Qt)
#ifndef TESTINTERFACE_H
#define TESTINTERFACE_H
 
#include <QObject>
 
class QString;
class QStringList;
 
class TestInterface : QObject{
   Q_OBJECT
public:
   virtual ~TestInterface() {}
   virtual QStringList operations() const = 0;
   virtual QString operation(const QString& strOperation ) = 0;
signals:
   void operationSelected(QString oper);
};
 
Q_DECLARE_INTERFACE(TestInterface, "ru.prog.PluginTest.TestInterface/1.1")
 
#endif // TESTINTERFACE_H
 

Плагин
Код
C++ (Qt)
#ifndef FRUITS_H
#define FRUITS_H
 
#include <QtCore>
#include "fruits_global.h"
#include "../TestInterface.h"
 
class FRUITSSHARED_EXPORT Fruits : public QObject, public TestInterface {
   Q_OBJECT
   Q_INTERFACES(TestInterface)
 
public:
   explicit Fruits(QObject *parent = 0);
   virtual ~Fruits();
 
   QStringList operations() const;
   QString operation(const QString &strOperation);
 
signals:
   void operationSelected(QString oper);
};
 
#endif // FRUITS_H
 


Код
C++ (Qt)
#include "fruits.h"
#include <QDebug>
 
Fruits::Fruits(QObject *parent) : QObject(parent)
{
}
 
Fruits::~Fruits()
{
 
}
 
QStringList Fruits::operations() const
{
   return QStringList() << "apple" << "grape" << "banana" << "kiwi";
}
 
QString Fruits::operation(const QString &strOperation)
{
   emit operationSelected(strOperation);
   if (strOperation == "apple") {return QString("i'm a Apple");}
   else if (strOperation == "grape") {return QString("i'm a Grape");}
   else if (strOperation == "banana") {return QString("i'm a Banana");}
   else if (strOperation == "kiwi") {return QString("i'm a Kiwi");}
   else {qDebug() << "unsupported operation"; return QString();}
}
 
Q_EXPORT_PLUGIN2(TestInterface, Fruits)
 
« Последнее редактирование: Сентябрь 07, 2012, 15:53 от lighting » Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


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