 |
|

03.09.2021, 19:52
|
|
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами:
4483143
Репутация:
183
|
|
ktsignalНебольшая библиотека сигналов для C++. Для компиляции потребуется C++17 (на MSVC можно скомпилировать на C++14)
Немного примеров кодаБазовое использование:Пример ниже показывает базовое использование сигналов
C++:
Код:
void
on_click
(
int
value
)
{
}
class
A
{
public
:
void
on_class_click
(
int
value
)
{
}
}
;
int
main
(
)
{
// Сигнал с сигнатурой функции в шаблонном параметре
ktsignal
::
ktsignal
click
{
}
;
// Подключение обычной функции
click
.
connect
(
on_click
)
;
// Подключение member function
A object
;
click
.
connect
(
&
object
,
&
A
::
on_class_click
)
;
// Подключение лямбда функции
click
.
connect
(
[
]
(
int
)
{
}
)
;
// Вызов коллбэков
click
.
emit
(
1
)
;
}
Scoped соединения автоматически отключаются в конце области видимости
C++:
[CODE]
void
on_click
(
int
value
)
{
}
class
A
{
public
:
void
on_class_click
(
int
value
)
{
}
}
;
int
main
(
)
{
ktsignal
::
ktsignal
click
{
}
;
{
auto
connection
=
click
.
scoped_connect
(
on_click
)
;
A object
;
auto
method_connection
=
click
.
scoped_connect
(
&
object
,
&
A
::
on_class_click
)
;
click
.
scoped_connect
(
[
]
(
int
v
)
{
std
::
cout
Подключение / Отключение коллбэков
C++:
Код:
auto
connection
=
click
.
connect
(
on_click
)
;
// Подключение лямбда функции
click
.
connect
(
[
]
(
int
)
{
}
)
;
// Вызов сигнала (on_click и lambda будут вызваны)
click
.
emit
(
1
)
;
// Отключение on_click коллбэка от сигнала
connection
.
disconnect
(
)
;
// Только лямбда будет вызвана
click
.
emit
(
1
)
;
Несколько важных замечаний об объекте
- можно создавать по умолчанию, перемещать, но не копировать.
- Вы должны убедиться, что соединение не будет использоваться после уничтожения сигнала.
Итерация через слоты сигналаВы можете итерироваться по сигналу через range-based for при этом получая значение возврата
C++:
[CODE]
int
on_click
(
int
value
)
{
return
5
;
}
int
on_click_second
(
int
value
)
{
return
1
;
}
int
main
(
)
{
ktsignal
::
ktsignal
click
{
}
;
click
.
connect
(
on_click
)
;
click
.
connect
(
on_click_second
)
;
// Будет выведено `emit_iterate returned 5 emit_iterate returned 1`
for
(
auto
returned
:
signal
.
emit_iterate
(
1
)
)
{
std
::
cout
Также вы легко можете использовать функции из стандартной библиотеки C++
C++:
[CODE]
int
on_click
(
int
value
)
{
return
5
;
}
int
on_click_second
(
int
value
)
{
return
1
;
}
int
main
(
)
{
ktsignal
::
ktsignal
click
{
}
;
click
.
connect
(
on_click
)
;
click
.
connect
(
on_click_second
)
;
auto
iterate
=
signal
.
emit_iterate
(
0
)
;
auto
accumulated
=
std
::
accumulate
(
iterate
.
begin
(
)
,
iterate
.
end
(
)
,
0
)
;
// Will display 6
std
::
cout
Использование ktsignal в многопоточном кодеДля многопоточного кода вы должны использовать
C++:
Код:
void
func_thread
(
int
v
)
{
std
::
cout
signal
{
}
;
signal
.
connect
(
func_thread
)
;
// Создание потока который сразу же вызовет emit
std
::
thread
(
[
&
signal
]
(
)
{
// Создание потока который вызовет emit спустя 100мс
std
::
thread
(
[
&
signal
]
(
)
{
std
::
this_thread
::
sleep_for
(
100
ms
)
;
signal
.
emit
(
1
)
;
}
)
.
detach
(
)
;
signal
.
emit
(
2
)
;
}
)
.
join
(
)
;
std
::
this_thread
::
sleep_for
(
1.5
s
)
;
}
Код:
Код:
Вывод:
[func_thread] - before sleep
[func_thread] - before sleep
[func_thread] - after sleep
[func_thread] - after sleep
C++:
Код:
void
func_thread
(
int
v
)
{
std
::
cout
signal
{
}
;
signal
.
connect
(
func_thread
)
;
// Создание потока который сразу же вызовет emit
std
::
thread
(
[
&
signal
]
(
)
{
// Создание потока который вызовет emit спустя 100мс
std
::
thread
(
[
&
signal
]
(
)
{
std
::
this_thread
::
sleep_for
(
100
ms
)
;
signal
.
emit
(
1
)
;
}
)
.
detach
(
)
;
signal
.
emit
(
2
)
;
}
)
.
join
(
)
;
std
::
this_thread
::
sleep_for
(
1.5
s
)
;
}
Код:
Код:
Вывод:
[func_thread] - before sleep
[func_thread] - after sleep
[func_thread] - before sleep
[func_thread] - after sleep
Download & Source:
GitHub - KiN4StAt/ktsignal
Contribute to KiN4StAt/ktsignal development by creating an account on GitHub.
github.com
|
|
|

03.09.2021, 21:33
|
|
Флудер
Регистрация: 26.10.2013
Сообщений: 4,924
С нами:
6603505
Репутация:
183
|
|
Сообщение от kin4stat
void func_thread(int v) { std::cout signal{}; signal.connect(func_thread); // Создание потока который сразу же вызовет emit std::thread([&signal]() { // Создание потока который вызовет emit спустя 100мс std::thread( [&signal]() { std::this_thread::sleep_for(100ms); signal.emit(1); } ).detach(); signal.emit(2); }).join(); std::this_thread::sleep_for(1.5s); }
как у тебя 1 и 2 в строку разворачивается? Где-то перегрузка опператора = или эти цифры что-то другое означают?
|
|
|

03.09.2021, 21:34
|
|
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами:
4483143
Репутация:
183
|
|
Сообщение от SR_team
как у тебя 1 и 2 в строку разворачивается? Где-то перегрузка опператора = или эти цифры что-то другое означают?
Как ты лайкнул, я зашел в тему и увидел что проебался в примере.
Исправил до того как ты написал этот ответ.
|
|
|

03.09.2021, 21:38
|
|
Флудер
Регистрация: 26.10.2013
Сообщений: 4,924
С нами:
6603505
Репутация:
183
|
|
Сообщение от kin4stat
Как ты лайкнул, я зашел в тему и увидел что проебался в примере.
Исправил до того как ты написал этот ответ.
Еще у тебя сигнатура позволяет возвращать что-то из сигналов. Как это работает? emit возвращает список результатов?
UPD: В примере многопоточки сигнал что-то возвращает int(int)
|
|
|

03.09.2021, 21:40
|
|
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами:
4483143
Репутация:
183
|
|
Сообщение от SR_team
Еще у тебя сигнатура позволяет возвращать что-то из сигналов. Как это работает? emit возвращает список результатов?
emit_iterate позволяет по ним итерироваться(оператор * у итератора делает вызов слота в сигнале).
Не стал делать вектор возвратных значений для emit чтобы не оверхеда. При желании есть emit_iterate который позволяет это сделать
|
|
|

03.09.2021, 21:42
|
|
Флудер
Регистрация: 26.10.2013
Сообщений: 4,924
С нами:
6603505
Репутация:
183
|
|
Сообщение от kin4stat
оператор * у итератора делает вызов слота в сигнале
Почему не оператор ()? Как это выглядит?
|
|
|

03.09.2021, 22:14
|
|
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами:
4483143
Репутация:
183
|
|
Сообщение от SR_team
Почему не оператор ()? Как это выглядит?
Оператор * перегружен для вызова функции, чтобы в range-based for можно было красиво получить возвратное значение. Да и в целом это позволяет много красивых вещей делать.
Ну например вот такое:
C++:
Код:
auto
iterate
=
signal
.
emit_iterate
(
"test"
)
;
std
::
vector
vec
(
iterate
.
begin
(
)
,
iterate
.
end
(
)
)
;
И в vec будут все значения которые вернулись после вызова коллбэков
(Только что залил обновление на гите, теперь на MSVC можно конструировать STL контейнеры через итераторы. Microsoft решили выебнуться проверкой на поля итератора)
Сообщение от SR_team
Почему не оператор ()?
Мне кажется что вызов сигнала через () не очень явное действие, поэтому решил сделать на emit. В целом это на сам сигнал никак не влияет
Сообщение от SR_team
Как это выглядит?
Примерно вот так:
Сообщение от SR_team
UPD: В примере многопоточки сигнал что-то возвращает int(int)
UPD: сигнал может что-то возвращать, но при вызове через emit эти значения получить нельзя. Для этих целей стоит юзать emit_iterate и его методы begin и end возвращающие итераторы
|
|
|

14.09.2021, 15:46
|
|
Познающий
Регистрация: 10.12.2016
Сообщений: 38
С нами:
4959604
Репутация:
73
|
|
qt на минималках
|
|
|

18.09.2021, 11:03
|
|
Познающий
Регистрация: 06.09.2018
Сообщений: 32
С нами:
4045092
Репутация:
23
|
|
дежавю от документации
|
|
|

18.09.2021, 12:11
|
|
Флудер
Регистрация: 06.11.2017
Сообщений: 2,759
С нами:
4483143
Репутация:
183
|
|
Сообщение от .deserve
дежавю от документации
Делал по принципу буста, доку сам писал, хз
|
|
|
|
 |
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|