Добавьте FDS в основной цикл GLIB

Мне нужно прикрепить файловые дескрипторы к основному циклу GLIB. Моя проблема в том, что список файловых дескрипторов не фиксируется во время выполнения.

Согласно документации GLIB, я могу:

  • создайте канал GIOC для каждого FD с помощью g_io_channel_unix_new и присоедините его к контексту с помощью g_io_add_watch
  • Используйте Gsource, созданный с помощью g_io_create_watch, и установите обратный вызов g_source_set_callback.

Мой вопрос: возможно ли динамическое изменение источника или контекста. И как я могу это сделать? Я нахожу способность GSourceFuncs, но это не соответствует моей проблеме.

Спасибо за вашу помощь.

3 ответа

g_io_add_watch возвращает идентификатор источника события, который вы можете позже использовать для динамического удаления часов, используя g_source_remove, Используйте один источник событий для FD и вместо изменения существующих часов удалите старые и создайте соответствующие новые.

Я больше копался в GLIB и теперь:

  • Я создаю источник с функциями обратного вызова (подготовка, проверка, отправка, завершение)
  • В обратном вызове подготовки FD удаляются с помощью g_source_remove_unix_fd(), а затем добавляются к текущему источнику с помощью g_source_add_unix_fd().
  • Я вернул FALSE, чтобы установить время ожидания (1 с для моего примера)

Моя проблема в том, что без FD обратный вызов prepare вызывается каждые 1, как и ожидалось. При добавлении FD обратный вызов prepare вызывается без тайм-аута. выход из опроса напрямую.

Я смотрю на исходный код GLIB, но не понимаю, почему?

Помогите пожалуйста С уважением

Ответ аменофики самый лучший.

Если вы хотите, чтобы ваш код работал со старым glib, вы можете использовать:

  • g_source_add_poll ()
  • g_source_remove_poll ()

Кажется, я нашла миниатюрный крючок. Попробуй это:

struct source {
    GSource gsrc;
    GPollFD *gpfd;
};

struct data {
    /* A something data. */
};

static gboolean gsrc_dispatch(GSource *gsrc, GSourceFunc cb, gpointer data);
static struct data * data_alloc(void);

static GSourceFuncs gsf = {
    .prepare = NULL,
    .check = NULL,
    .dispatch = gsrc_dispatch,
    .finalize = NULL
};

int main(void)
{
    struct source *src;
    int fd;
    struct data *data = data_alloc();

    /* Something other. */

    /* For example, we are want to capture video from a camera. */
    fd = open("/dev/video0", O_RDWR);
    if (fd < 0) {
        perror("open()");

        return -1;
    }

    src = (struct source *) g_source_new(&gsf, sizeof(struct source));
    src->gpfd = g_source_add_unix_fd((GSource *) src, fd, G_IO_IN);

    g_source_set_callback((GSource *) src, NULL, data, NULL);
    g_source_attach((GSource *) src, NULL);

    /* Something other and free. */

    return 0;
}

static gboolean
gsrc_dispatch(GSource *gsrc, GSourceFunc cb, gpointer data)
{
    struct source *src = (struct source *) gsrc;
    struct data *d = data;

    if (src->gpfd != NULL) {
        if (src->gpfd->revents & G_IO_IN) {
            /* Capture a frame. */
        }
    }

    g_main_context_iteration(NULL, TRUE);

    return G_SOURCE_CONTINUE;
}

static struct data *
data_alloc(void)
{
    /* Allocate a data. */
}

Да, вы можете использовать двойной gpfd указатель.

Вы читали документацию по Main Event Loop? В разделе описания есть довольно хорошее объяснение того, как все работает.

Вы смотрели учебник по пользовательскому GSource? Это позволяет расширить объект GSource, включив в него ваше собственное состояние. Вы также можете написать свои собственные функции подготовки, отправки, запроса и проверки.

Всякий раз, когда я действительно хочу увидеть, как что-то сделать с GLib, GTK и т. Д., Первое, на что я обращаю внимание, это тестовый код, который находится в их git-репозитории. Обязательно извлеките соответствующий тег для версии, на которую вы нацеливаетесь.

Например я в настоящее время нацеливаюсь на 2.48.2

Вот два довольно хороших примера https://gitlab.gnome.org/GNOME/glib/blob/2.48.2/tests/mainloop-test.c https://gitlab.gnome.org/GNOME/glib/blob/2.48.2/glib/tests/mainloop.c

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

Другие вопросы по тегам