LINUX.ORG.RU

Помогите разобраться с GSources, GMainContext.

 event source, , ,


0

1

Помогите разобраться с источниками событий (GSource, GIOSource), контекстами (GMainContext) и обработчиками этих событий.

У меня есть Beaglebone, на котором я хочу обрабатывать прерывание изменения уровня на одном из GPIO. Вот пример того как это делается на C. Для Ъ:

struct pollfd pfd[1];
pfd[0].fd = open ("/sys/class/gpio/gpio34/value", O_RDONLY);
pfd[0].event = POLLPRI;
pfd[0].revent = 0;

while (1) {
    poll (pfd, 1, -2);
    something_useful ();
}
Функция poll() не завершается пока не происходит событие на которое настроено прерывание. Когда это событие происходит выполнение poll() завершается, выполняется какая-то полезная функция, после чего снова переходим к функции poll() и ожидаем события.

А теперь вопрос, как это сделать с использованием GLib, желательно даже на Vala, но и на C пойдёт.

Правильно я понимаю, что «вместо» while (1) будет GMainLoop? Правильно ли я понимаю, что нужно в каком-то контексте завести источник событий (GIOSource?) ? А ещё нужно к чему-то прицепить g_source_add_poll() и g_source_set_callback(). Может кто-нибудь показать пример кода?

★★★★★

Примерно так:

    GSource *source = g_source_new(&source_funcs,
                                      sizeof(GSource));
    GPollFD pollfd;;
    pollfd.fd = open(...);
    pollfd.events = POLLIN|POLLERR|POLLPRI;
    pollfd.revents = 0;
    g_source_add_poll(source, &pollfd);
    g_source_attach(source, NULL);

    g_idle_add(something_useful, NULL);
    g_main_loop_run(g_main_loop_new(NULL, 0));

Вместо последних двух строк можно сделать

    while(1) {
        g_main_context_iteration(NULL, 1);
        something_useful();
    }

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

Разобрался.

Спасибо, я сам уже разобрался, у меня код такой:

class Beaglebone : GLib.Object {
    public static int main (string[] args) {
        message ("Beaglebone running.\n");
		MainLoop loop = new MainLoop ();

		IOChannel channel = new IOChannel.file("/sys/class/gpio/gpio22/value", "r");

		uint stat = channel.add_watch (IOCondition.PRI, source, condition) => {
				size_t terminator_pos = -1;
				string str_return = null;
				size_t length = -1;

				try {
					IOStatus status = channel.read_line (out str_return, out length, out terminator_pos);
					stdout.printf ("Something useful here.\n");
					return true;
				} catch (IOChannelError e) {
					stdout.printf ("IOChannel error: %s\n", e.message);
					return false;
				} catch (ConvertError e) {
					stdout.printf ("ConvertError %s\n", e.message);
					return false;
				}
			});

		if (stat == 0) {
			stdout.printf ("Cannot add watch.\n");
			return 0;
		}

		loop.run ();
		message ("Beaglebone stopped.\n");
        return 0;
    }
}
Недостаток в том, что функция срабатывает (в смысле выводит something useful here) при запуске программы, поскольку в файле в этот момент уже лежит 0 или 1.

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