LINUX.ORG.RU

А ты не исходники смотри, а то что получается после moc. Или почитай про паттерн Command.

wfrr ★★☆
()
Ответ на: комментарий от wfrr

> А ты не исходники смотри, а то что получается после moc.

Я так и делаю. Только хочется спросить имеющих опыт людей. Может оно в принципе в таком виде не реализуется средствами С.

Rarruga
() автор топика

Есть такая библиотека для С, которая реализует event-driven логику и распределенные вычисления. Называется erlang :))

Macil ★★★★★
()
Ответ на: комментарий от Rarruga

> Я так и делаю. Только хочется спросить имеющих опыт людей. Может оно в принципе в таком виде не реализуется средствами С.

Ц - это ассемблер. а значит реализуется ВСЕ.

anonymous
()
Ответ на: комментарий от Macil

> Есть такая библиотека для С, которая реализует event-driven логику и распределенные вычисления. Называется erlang :))

Спасибо, посмотрю.

Rarruga
() автор топика
Ответ на: комментарий от anonymous

> Ц - это ассемблер. а значит реализуется ВСЕ.

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

Rarruga
() автор топика
Ответ на: комментарий от Macil

> Есть такая библиотека для С, которая реализует event-driven логику и распределенные вычисления. Называется erlang :))

Вы меня обманули.:) Это язык такой. А мне нужно на чистом С.

Rarruga
() автор топика
Ответ на: комментарий от anonymous

Qtшные signal-slots основаны на знании мета-информации (RTTI,
Reflection, OLE/COM etc.) - это, когда "изнутри кода" известно "всё" 
о методах класса, функциях и имеется способ "добраться" до их указателей
(function pointers).
Альтернативные методы здесь: 
http://en.wikipedia.org/wiki/Signals_and_slots

Valeriy_Onuchin ★★
()

> Как концептуально это сделать? Ищу любую информацию по этой теме.

1. libsig++ -- но оно для ++
2. википедия
3. GObject
4. Objective C, передача сообщений, исходники POC и ObjC runtime на Си
5. лисп, generic function в CLOS; разница vtable и generic function
6. конечные автоматы, Ragel, SWITCH-технология
7. io, javascript, self -- прототипы, слоты, интроспекция
...

anonymous
()
Ответ на: комментарий от Rarruga

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

А оно там элегантно выглядит?

mv ★★★★★
()
Ответ на: комментарий от xydo

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

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

причем, там чуть ли не case-ы были...

ух, как вспомню, мурашки по коже.

дело было правда года 1,5 назад. как сейчас - не знаю.

xydo ★★
()
Ответ на: комментарий от mv

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

> А оно там элегантно выглядит?

По моему ограниченному опыту, да. Признаю, что наверное есть лучше.

Rarruga
() автор топика
Ответ на: комментарий от xydo

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

> каждый частный сигнал передавал в общую функцию свой id, там он распознавался, вызывался внутренний частный обработчик, они уже опять генерили какой-то id, передавали в общую функцию, а она уже распознавала и вызывала слот. что-то в этом духе было...

> причем, там чуть ли не case-ы были...

> ух, как вспомню, мурашки по коже.

> дело было правда года 1,5 назад. как сейчас - не знаю.

Вот интересно как оно в Qt устроено в принципе. И как оно будет работать если есть много (сотни-тысячи) связок сигнал-слот. Может такая архитектура мне и не нужна. Привлекает то, что все скрыто от программиста и просто делаются connect-ты. Правда эта простота во-многом за счет moc-а, но может как-то можно было бы это дело макросами сделать.

А switch/case есть по крайней мере в генерируемых moc-файлах.

Rarruga
() автор топика
Ответ на: комментарий от Rarruga

> А switch/case есть по крайней мере в генерируемых moc-файлах.
Правда чоль? Если да - то даже гений Тролльтехов оказался бессилен перед кривизной недоязычка. Когда в ОО языке нельзя реализовать нормальный ОО без свитчей... Ха!

svu ★★★★★
()
Ответ на: комментарий от svu

Ну вот, например, что оно сгенерило для моего класса MainWindow:

int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a) { _id = QMainWindow::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod) { switch (_id) { case 0: projectDeleted((*reinterpret_cast< QWidget*(*)>(_a[1]))); break; case 1: about(); break; case 2: newFile(); break; case 3: open(); break; case 4: openRecentFile(); break; case 5: save(); break; case 6: saveAs(); break; case 7: close(); break; case 8: closeall(); break; case 9: prefs(); break; case 10: updateWindowMenu(); break; case 11: setActiveSubWindow((*reinterpret_cast< QWidget*(*)>(_a[1]))); break; case 12: importdata(); break; case 13: fullscreen(); break; case 14: ToolsGEDint(); break; case 15: ToolsImageViewer(); break; case 16: ToolsPeriodicTable(); break; case 17: explorerTabChanged((*reinterpret_cast< int(*)>(_a[1]))); break; case 18: updateMenusState(); break; } _id -= 19; } return _id; }

case 1-18 - это мои функции, объявленные как SLOT. case 0 - это мой собственный сигнал.

Есть у меня подозрение, что в Qt делается полный обход всех возможных слотов всех объектов при возникновении сигнала. Это, конечно, плохо (если правда).

Rarruga
() автор топика
Ответ на: комментарий от svu

Ну вот, например, что оно сгенерило для моего класса MainWindow:

int MainWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QMainWindow::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: projectDeleted((*reinterpret_cast< QWidget*(*)>(_a[1]))); break;
        case 1: about(); break;
        case 2: newFile(); break;
        case 3: open(); break;
        case 4: openRecentFile(); break;
        case 5: save(); break;
        case 6: saveAs(); break;
        case 7: close(); break;
        case 8: closeall(); break;
        case 9: prefs(); break;
        case 10: updateWindowMenu(); break;
        case 11: setActiveSubWindow((*reinterpret_cast< QWidget*(*)>(_a[1]))); break;
        case 12: importdata(); break;
        case 13: fullscreen(); break;
        case 14: ToolsGEDint(); break;
        case 15: ToolsImageViewer(); break;
        case 16: ToolsPeriodicTable(); break;
        case 17: explorerTabChanged((*reinterpret_cast< int(*)>(_a[1]))); break;
        case 18: updateMenusState(); break;
        }
        _id -= 19;
    }
    return _id;
}

case 1-18 - это мои функции, объявленные как SLOT.
case 0 - это мой собственный сигнал.

Есть у меня подозрение, что в Qt делается полный обход всех возможных слотов всех объектов при возникновении сигнала. Это, конечно, плохо (если правда).

Rarruga
() автор топика
Ответ на: комментарий от Rarruga

В общем для моей задачи думается просто сделать в каждом объекте динамический список callback-ов и указателей на другие объекты, которые будут передаваться в эти callback-и.

Rarruga
() автор топика
Ответ на: комментарий от Rarruga

Сладостно.

Нет, конечно, на С оно вряд ли бы выглядело лучше, скорее наоборот. Но С хотя бы не утверждает, что он ОО.

svu ★★★★★
()
Ответ на: комментарий от Rarruga

Кутишные сигналы со слотами -- всего лишь извращенный вызов коллбэков.

> ...думается просто сделать в каждом объекте динамический список callback-ов и указателей на другие объекты, которые будут передаваться в эти callback-и.

Вообще говоря, есть даже специальный design pattern "Observer", который является более общим.

Я б просто в каждом объекте с "сигналами" определил массив списков каллбэков. Сами сигналы -- целые (именованные) константы, индексирующие этот массив. При "связывании" сигнала со "слотом" к соответствующему элементу массива добавляется ссылка на callback (т.е., на этот слот). А параметры передавать можно просто универсально, через void *.

Die-Hard ★★★★★
()
Ответ на: комментарий от svu

> Ключевое слово - _массив_. А не switch/case

В разумных пределах (порядка сотни case) switch компилится в вычисляемый goto, что практически то же самое.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Кстати, "динамического" свитча в Це и нету.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Вообще говоря, есть даже специальный design pattern "Observer", который является более общим.

> Я б просто в каждом объекте с "сигналами" определил массив списков каллбэков. Сами сигналы -- целые (именованные) константы, индексирующие этот массив. При "связывании" сигнала со "слотом" к соответствующему элементу массива добавляется ссылка на callback (т.е., на этот слот). А параметры передавать можно просто универсально, через void *.

Да-да, примерно так я себе это и представляю. Только мутновато пока все в голове. Нужно делать, там прояснится.

Rarruga
() автор топика

тупо и в лоб:

static volatile uint8_t cmd_queue[CMD_QUEUE_SIZE];
static volatile uint8_t rly_queue[RLY_QUEUE_SIZE];
static volatile uint8_t cmd_head;
static volatile uint8_t cmd_tail;
static volatile uint8_t rly_head;
static volatile uint8_t rly_tail;

static void cmd_init(void)
{
  cmd_head = 0;
  cmd_tail = 0;
  rly_head = 0;
  rly_tail = 0;
}

static uint8_t cmd_put(uint8_t cmd)
{
  register uint8_t tmp;
  tmp = (cmd_head + 1) % CMD_QUEUE_SIZE;
  if (cmd_head == tmp)
  {
    return 0;
  }
  cmd_head = tmp;
  cmd_queue[tmp] = cmd;
  return 1;
}

#define cmd_empty (cmd_head == cmd_tail)

static uint8_t cmd_get(void)
{
  register uint8_t tmp;
  if (cmd_head == cmd_tail)
  {
    return 0xff; /* NO_CMD: OVF/UDF */
  }
  tmp = (cmd_tail + 1) % CMD_QUEUE_SIZE;
  cmd_tail = tmp;
  return cmd_queue[tmp];
}

static void rly_put(uint8_t rly)
{
  register uint8_t tmp;
  tmp = (rly_head + 1) % RLY_QUEUE_SIZE;
  while (tmp == rly_tail);
  rly_queue[tmp] = rly;
  rly_head = tmp;
}

static uint8_t rly_get(void)
{
  register uint8_t tmp;
  if (rly_head == rly_tail)
  {
    return 0xff; /* NO_RLY: OVF/UDF */
  }
  tmp = (rly_tail + 1) % RLY_QUEUE_SIZE;
  rly_tail = tmp;
  return rly_queue[tmp];
}

static void cmd_handle(void)
{
  static uint8_t state = 0;
  register uint8_t cmd;
  if (cmd_empty) return;
  cmd = cmd_get();
  switch (state)
  {
    case 0:
    {
      switch (cmd)
      {
        case CMD_REBOOT:
        {
          reboot();
        } break;
        case CMD_SET_TIMEOUT:
        {
          state = cmd;
        } break;
        default:
          state = 0;
      }
    } break;
    case CMD_SET_TIMEOUT:
    {
      set_timeout(cmd);
      state = 0;
    } break;
    default:
      state = 0;
  }
}

trapezoid
()
Ответ на: комментарий от tailgunner

>> Но С хотя бы не утверждает, что он ОО.

> А Си++ не утверждает, что он динамически типизирован.

Не в тему! Это трольтеховская поделка -- не совсем С++ на самом деле.

Сигнал-слот не требует офигенной динамической типизации, и делается с шаблонами вполне прилично (как обычно, статически типизровано, т.е. более надежно, чем у трольтехов)

(А плюсы достаточно прилично динамически типизированы, хотя не спорю, что там проблемы можно найти, но НЕ для этого случая ИМХО).

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от svu

> ОО без динамической типизации уныл чуть менее чем просто отсутствие ОО вообще.

Это НЕ про плюсы. Там достаточно динамической типизации, чтобы можно было повторить любой код из явы.

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от svu

>> А switch/case есть по крайней мере в генерируемых moc-файлах.

> Правда чоль? Если да - то даже гений Тролльтехов оказался бессилен перед кривизной недоязычка. Когда в ОО языке нельзя реализовать нормальный ОО без свитчей... Ха!

Ничего подобного. Это трольтехи писали свою фигню, когда компиляторы не держали шаблоны должным образом, а сейчас все переписывать под С++ не хотят.

www_linux_org_ru ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.