2

我需要将文件描述符附加到 GLIB 主循环。我的问题是文件描述符列表在执行期间没有固定。

根据 GLIB 文档,我可以:

  • 使用 g_io_channel_unix_new为每个 FD创建一个GIOChannel并使用g_io_add_watch将其附加到上下文
  • 使用通过g_io_create_watch创建的Gsource并设置回调g_source_set_callback

我的问题是:是否可以动态修改源或上下文。我该怎么做?我发现 GSourceFuncs 能力,但这不适合我的问题。

谢谢你的帮助。

4

5 回答 5

2

g_io_add_watch返回一个事件源 ID,您以后可以使用它来再次动态删除手表,使用g_source_remove. 每个 FD 使用一个事件源,而不是修改现有的监视,删除旧的并创建适当的新监视。

于 2014-05-21T11:34:56.087 回答
1

我更深入地研究了 GLIB,现在:

  • 我创建了一个带有回调函数的源(准备、检查、调度、完成)
  • 在准备回调中,FD 使用 g_source_remove_unix_fd() 删除,然后使用 g_source_add_unix_fd() 添加到当前源。
  • 我返回 FALSE 来设置超时(我的例子是 1s)

我的问题是,如果没有 FD,prepare 回调会按预期每 1 秒调用一次。添加 FD 时,会调用 prepare 回调而不会超时。投票直接退出。

我查看了 GLIB 源代码,但不明白为什么?

帮助请问候

于 2014-06-03T11:54:53.483 回答
0

amenophiks 的回答是最好的。

如果您希望您的代码与较旧的 glib 一起使用,您可以使用:

  • g_source_add_poll()
  • g_source_remove_poll()
于 2015-01-20T09:59:40.547 回答
0

看来,我找到了一个小钩子。尝试这个:

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指针。

于 2020-02-14T21:37:34.443 回答
0

您是否阅读过主事件循环文档?描述部分很好地解释了事情是如何工作的。

你看过自定义 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 存储库,因此您可以非常轻松地搜索它。

于 2019-05-30T15:43:21.187 回答