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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [РЕШЕНО] Массив сигналов...  (Прочитано 12797 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Октябрь 15, 2014, 21:32 »

Нужно собрать однотипные сигналы в массив и эмитировать их по номеру. Но в C++ запрещено получать адрес функции-члена класса для динамического объекта. А статический вариант не приемлем для сигналов, при emit используется адрес несуществующего объекта. Подключения сигналов могут динамически меняться, поэтому invokeMethod не годится. Можно, конечно, влоб длинный switch/case написать (на самом деле, оптимизатор такую колбасу в массив и загоняет), этих сигналов не так много. Но может есть какие-то подводные возможности... В описаниях всяких "мета" ничего подходящего не нашел. Хотя заглянул в исходники Qt - там внутри после входа в мета-функцию сигнала дальше производится обработка по номерам. Может есть какой легальный, но недокументированный способ для QObject эмитировать свой сигнал по его номеру?
« Последнее редактирование: Октябрь 16, 2014, 22:03 от Гурман » Записан

2^7-1 == 127, задумайтесь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #1 : Октябрь 15, 2014, 22:58 »

Цитировать
Но в C++ запрещено получать адрес функции-члена класса для динамического объекта.
Да ладно? O_o
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #2 : Октябрь 15, 2014, 23:24 »

Цитировать
Но в C++ запрещено получать адрес функции-члена класса для динамического объекта.
Да ладно? O_o

Код:
typedef void ( *sox )( QVariant );

class CiControl : public QObject
{
...
signals:    
    void universalOut01(QVariant);
...
private:
    sox sigarray[32];
}


SEGINTERFACES* CiControl::getInterfaces()
{
...
    sigarray[0] = (sox) &universalOut01; // строка 93
...
}

Цитировать
I:\Qt\2010.05s\citypes\Documents\cincontrol-build-desktop\..\cicontrol\cicontrol.cpp:93: ошибка: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say '&CiControl::universalOut01
- то есть, статически можно, и

Код:
SEGINTERFACES* CiControl::getInterfaces()
{
...
    sigarray[0] = (sox) &CiControl::universalOut01;
...
}

компилируется, но не работает, при попытке emit sigarray[0]( variant ); падает глубоко внутри Qt, поскольку this там содержит адрес вовсе не того же инстанса объекта, в котором делается emit

на самом деле, запрет правильный, поскольку это источник дырок

но вопрос был не об этом
« Последнее редактирование: Октябрь 15, 2014, 23:33 от Гурман » Записан

2^7-1 == 127, задумайтесь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #3 : Октябрь 15, 2014, 23:54 »

Если я правильно понял, то я бы сделал как то так:

Код
C++ (Qt)
class CiControl : public QObject
{
public:
   signal<QVariant> sigarray[32];    
 
}
 
Сигналы бы использовал либо бустовские, либо, например ssp::signal http://www.prog.org.ru/topic_16829_105.html (https://www.gitorious.org/lightssp)

Пример для ssp::signal, это выглядело бы так:
Код
C++ (Qt)
#include <signal_slot.h>
 
class CiControl
{
public:
   ssp::signal<int> sigarray[32];
};
 
class A : public ssp::trackable
{
public:
   void slot1(int arg) { std::cout << "A::slot1(int arg); arg = " << arg << std::endl; }
   void slot2(int arg) { std::cout << "A::slot2(int arg); arg = " << arg << std::endl; }
};
 
int main()
{
   CiControl ci_control;
 
   A a1, a2;
 
   ci_control.sigarray[0].connect(&a1, &A::slot1);
   ci_control.sigarray[0].connect(&a1, &A::slot2);
   ci_control.sigarray[1].connect(&a2, &A::slot1);
   ci_control.sigarray[1].connect(&a2, &A::slot2);
 
   ci_control.sigarray[0](1005001);
   ci_control.sigarray[1](1005002);
 
   return 0;
}
 
« Последнее редактирование: Октябрь 16, 2014, 00:50 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Октябрь 16, 2014, 09:23 »

В описаниях всяких "мета" ничего подходящего не нашел.
А примерчик в QMetaObject::methodCount ? Во всяком случае имена всех сигналов есть, типы аргументов тоже. Напр PythonQt такими вызовами занимается, так что дело рядовое (и документированное).  Что имелось ввиду под "номером" - хз, поэтому больше сказать нечего.
« Последнее редактирование: Октябрь 16, 2014, 09:25 от Igors » Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #5 : Октябрь 16, 2014, 10:23 »

В описаниях всяких "мета" ничего подходящего не нашел.
А примерчик в QMetaObject::methodCount ? Во всяком случае имена всех сигналов есть, типы аргументов тоже. Напр PythonQt такими вызовами занимается, так что дело рядовое (и документированное).  Что имелось ввиду под "номером" - хз, поэтому больше сказать нечего.

methodCount просто возвращает количество методов, включая не-сигналы - пользы от него никакой

"по номеру" означает, по целочисленному индексу

Сигналы бы использовал либо бустовские, либо, например ssp

ни boost, ни ssp не используются по техническим условиям, только Qt

патамушта...

Записан

2^7-1 == 127, задумайтесь...
Johnik
Крякер
****
Offline Offline

Сообщений: 339


Просмотр профиля
« Ответ #6 : Октябрь 16, 2014, 10:42 »

methodCount просто возвращает количество методов, включая не-сигналы - пользы от него никакой
далее получаем информацию по методу:
Код
C++ (Qt)
QMetaMethod QMetaObject::method(int index) const
и QMetaMethod содержит:
Код
C++ (Qt)
MethodType QMetaMethod::methodType() const

Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #7 : Октябрь 16, 2014, 10:45 »

methodCount просто возвращает количество методов, включая не-сигналы - пользы от него никакой

"по номеру" означает, по целочисленному индексу
Впечатление что Вы раздражены, типа "ну чего всякую ерунду пердлагаете" Улыбающийся А может это не ерунда? Вот кусок кода выдрал наобум из PythonQt
Код
C++ (Qt)
   const QMetaObject* meta = decoratorProvider->metaObject();
   int numMethods = meta->methodCount();
   int startFrom = QObject::staticMetaObject.methodCount();
   for (int i = startFrom; i < numMethods; i++) {
     QMetaMethod m = meta->method(i);
     if ((m.methodType() == QMetaMethod::Method ||
          m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
 
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #8 : Октябрь 16, 2014, 11:05 »

ни boost, ни ssp не используются по техническим условиям, только Qt

патамушта...

Ну так такое поведение можно реализовать и с Qt-шными сигналами..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #9 : Октябрь 16, 2014, 11:11 »

methodCount просто возвращает количество методов, включая не-сигналы - пользы от него никакой

"по номеру" означает, по целочисленному индексу
Впечатление что Вы раздражены, типа "ну чего всякую ерунду пердлагаете" Улыбающийся А может это не ерунда? Вот кусок кода выдрал наобум из PythonQt
Код
C++ (Qt)
   const QMetaObject* meta = decoratorProvider->metaObject();
   int numMethods = meta->methodCount();
   int startFrom = QObject::staticMetaObject.methodCount();
   for (int i = startFrom; i < numMethods; i++) {
     QMetaMethod m = meta->method(i);
     if ((m.methodType() == QMetaMethod::Method ||
          m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
 

И вызывать этот мета-метод через invoke()?... Вай. Ну может быть, так и можно, хотя выглядит шибко громоздко. Возможно это вариант решения. Пока наваял switch/case и он работает, причем наверняка быстрее, чем такие макароны. И выглядит даже изящнее.

Код:
            switch( i )
            {
            case 0: emit universalOut01( container ); break;
            case 1: emit universalOut02( container ); break;
            ....
            }
« Последнее редактирование: Октябрь 16, 2014, 11:13 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Октябрь 16, 2014, 11:31 »

И вызывать этот мета-метод через invoke()?... Вай. Ну может быть, так и можно, хотя выглядит шибко громоздко. Возможно это вариант решения. Пока наваял switch/case и он работает, причем наверняка быстрее, чем такие макароны. И выглядит даже изящнее.
Ну чтобы так наваять не нужно создавать тему на форуме  Улыбающийся
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #11 : Октябрь 16, 2014, 11:36 »

И вызывать этот мета-метод через invoke()?... Вай. Ну может быть, так и можно, хотя выглядит шибко громоздко. Возможно это вариант решения. Пока наваял switch/case и он работает, причем наверняка быстрее, чем такие макароны. И выглядит даже изящнее.
Ну чтобы так наваять не нужно создавать тему на форуме  Улыбающийся

Ситуация может поменяться. Для этого объекта пока хватило такого варианта, для другого уже может быть не пригодно. Или для этого может.

Эх... вот если бы еще можно было методы добавлять динамически... Ну, например, размножением - описал один сигнал, а потом в рантайме добавил еще один такой же, с динамическим формированием имени. И еще...
Записан

2^7-1 == 127, задумайтесь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #12 : Октябрь 16, 2014, 12:05 »

Да просто заверните сигнал в свой объект и создавайте потом из них хоть массив, хоть что (псевдокод):

Код
C++ (Qt)
class signal_wrapper : public QObject
{
...
signals:
   void signal(QVariant);
 
};
 
class CiControl : public QObject
{
public:
   signal_wrapper sigarray[32];    
 
}
 
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #13 : Октябрь 16, 2014, 12:11 »

Да просто заверните сигнал в свой объект и создавайте потом из них хоть массив, хоть что (псевдокод):

Код
C++ (Qt)
class signal_wrapper : public QObject
{
...
signals:
   void signal(QVariant);
 
};
 
class CiControl : public QObject
{
public:
   signal_wrapper sigarray[32];    
 
}
 

Не годится. Подключать (connect) придется не тот объект, который де-факто является источником сигналов. А это по задаче существенно. Получатель определяет, от кого пришел сигнал с помощью QSignalMaper. Да и не только по этой причине.

Записан

2^7-1 == 127, задумайтесь...
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4349



Просмотр профиля
« Ответ #14 : Октябрь 16, 2014, 13:01 »

Код
C++ (Qt)
#ifndef OBJECT_H
#define OBJECT_H
 
#include <QObject>
#include <QVector>
 
class Object : public QObject
{
Q_OBJECT
public:
explicit Object( QObject *parent = 0 );
 
void emitNum( int index, const QVariant &val );
 
signals:
void sig0( const QVariant &val );
void sig1( const QVariant &val );
void sig2( const QVariant &val );
void sig3( const QVariant &val );
void sig4( const QVariant &val );
 
private:
typedef void (Object::*signal_ptr)( const QVariant &val );
QVector<signal_ptr> m_sigs;
};
 
#endif // OBJECT_H
 

Код
C++ (Qt)
#include "object.h"
 
Object::Object( QObject *parent ) :
QObject( parent ),
m_sigs( 5 )
{
m_sigs[ 0 ] = &Object::sig0;
m_sigs[ 1 ] = &Object::sig1;
m_sigs[ 2 ] = &Object::sig2;
m_sigs[ 3 ] = &Object::sig3;
m_sigs[ 4 ] = &Object::sig4;
}
 
void Object::emitNum( int index , const QVariant &val )
{
Q_ASSERT( index >= 0 && index < m_sigs.size() );
signal_ptr func = m_sigs[ index ];
(this->*func)( val );
}
 
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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