c -在GLIB主循环中添加fds



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

根据GLIB文档,我可以:

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

我的问题是:是否有可能动态修改源或上下文。我该怎么做呢?我找到了GSourceFuncs的能力,但这并不适合我的问题。

谢谢你的帮助。

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

我深入研究了GLIB,现在:

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

我的问题是,没有FD,准备回调按预期每隔15秒调用一次。当添加FD时,将不超时地调用prepare回调。投票直接退出。

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

请帮助关于

健忘者的答案是最好的。

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

  • g_source_add_poll ()
  • g_source_remove_poll ()

你读过主事件循环文档吗?描述部分很好地解释了工作原理。

你看过自定义GSource教程吗?这允许你扩展GSource对象来包含你自己的状态。您还可以编写自己的准备、调度、查询和检查函数。

每当我真的想看看应该如何使用GLib, GTK等来完成某事时,我首先要看的是git存储库中的测试代码。请确保为目标版本签出正确的标签。

例如,我当前的目标2.48.2

这里有两个很好的例子https://gitlab.gnome.org/GNOME/glib/blob/2.48.2/tests/mainloop-test.chttps://gitlab.gnome.org/GNOME/glib/blob/2.48.2/glib/tests/mainloop.c

另一个很好的特性是它是一个git存储库,所以你可以很容易地搜索它。

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

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

最新更新