LINUX.ORG.RU

OpenCV, обработка событий оконной системы и файловые дескрипторы

 , ,


2

1

Решение проблемы: OpenCV, обработка событий оконной системы и файловые дескрипторы (комментарий)


Привет всем!

Сразу говорю, хочется достаточно странного. Собственно в тегах это и указано. Пишу на Python небольшую софтинку с использованием OpenCV. Кроме обработки изображений OpenCV используется и для GUI. Это удобно, особенно в процессе отладки, т.к. не возникает необходимости в дополнительных манипуляциях с картинкой перед отображением, а можно просто показать с помощью cv2.imshow(). Да, я знаю, что модуль High-level GUI не предназначен для сложных интерфейсов и об этом прямо говорится в документации.

Проблема в том, что для работы GUI из OpenCV надо периодически дёргать cv2.waitKey(). Обычно это делается в цикле while True:. Но у меня есть другие источники событий, работа с которыми осуществляется через файловые дескрипторы. Т.е. цикл обработки событий через select / poll / epoll. Логичным было бы файловый дескриптор от unix-сокета, соответствующего подключению к X11-серверу добавить в этот цикл обработки событий и cv2.waitKey() вызывать только тогда, когда там есть данные, а не по таймауту или в цикле while True:.

Возникает вопрос. Как узнать номер нужного файлового дескриптора? Есть посмотреть содержимое /proc/self/fd/, то там явно есть нужный дескриптор:

0 -> /dev/pts/1
1 -> /dev/pts/1
2 -> /dev/pts/1
3 -> anon_inode:[eventfd]
4 -> pipe:[576490]
5 -> pipe:[576490]
6 -> socket:[576491]
7 -> socket:[576492]

Дескрипторы с номером больше 2 открываются после вызова cv2.namedWindow(). Как узнать, какой из них какой?

Как вообще в общем случае узнать какому объекту файловой системы соответствует ссылка вида socket:[number] в /proc/self/fd/?

★★★★★

Последнее исправление: ls-h (всего исправлений: 1)

Как вообще в общем случае узнать какому объекту

Не надо путать тёплое с мягким. Если «объект» сам каким-либо образом не сообщает о себе, то определить его «наличие» не является ни «общей», ни «тривиальной» задачей.

anonymous
()

Базовую (но недостаточную) информацию можно получить используя readlink() и lstat() для каждого файла из /proc/self/fd/.

После этого, чтобы узнать где другой «конец» unix-сокета, пользовать один из вариантов в ответах.

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

Базовую (но недостаточную) информацию можно получить используя readlink()

Через `readlink()` я и получаю `6 -> socket:[576491]`. Чем должен помочь `lstat()` я не очень понял. В принципе, `ss -a --unix -p` помогает найти другой конец. Только как бы это сделать программно, без вызова внешней утилиты?

Спасибо!

ls-h ★★★★★
() автор топика
Ответ на: комментарий от ls-h

Через readlink() я и получаю 6 -> socket:[576491]. Чем должен помочь lstat() я не очень понял.

У меня почему-то стойкое «дежавю» что когда-то/раньше там не было «socket». Но может быть я когда-то использовал lstat оптом для какой-то обвязки на C++.

Только как бы это сделать программно, без вызова внешней утилиты?

В одном из ответов точно была ссылка на репу на github. Ну и что мешает глянуть в исходники ss?

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

Ну и что мешает глянуть в исходники ss?

Гляжу, пока не нашёл, откуда оно берёт соответствие двух концов...

ls-h ★★★★★
() автор топика
Ответ на: комментарий от ls-h

Гляжу, пока не нашёл, откуда оно берёт соответствие двух концов…

90% информации там читается через netlink, но возможно проще протрассировать запустив с нужными опциями. Как вариант - под rr.

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

90% информации там читается через netlink

Да, замудрёная штука получается, особенно из Python'а. А нет какого-либо более прямого пути? Ведь файловый дескриптор открыт внутри моего процесса, и при его открытии явно был передан искомый путь.

ls-h ★★★★★
() автор топика
Ответ на: комментарий от ls-h

Да, замудрёная штука получается, особенно из Python’а. А нет какого-либо более прямого пути? Ведь файловый дескриптор открыт внутри моего процесса, и при его открытии явно был передан искомый путь.

см getsockname() и getpeername() для unix-сокетов.

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

см getsockname() и getpeername() для unix-сокетов.

Вот это оно. getpeername() для нужного дескриптора возвращает '\x00/tmp/.X11-unix/X0'.

Огромное спасибо! Держи плюсик в карму! Ах да... Тут нет кармы.

ls-h ★★★★★
() автор топика

Что мешает waitKey засунуть в отдельный поток, который будет выставлять флаг события (или таймстемп последнего нажатия). Тогда в основном потоке легко сможешь обрабатывать его в стиле poll/epoll.

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